Skip to content

Commit

Permalink
Merge pull request #60 from pactus-project/feat/l10n-centralize-trans…
Browse files Browse the repository at this point in the history
…lation-keys

refactor: use `l10n` for localization and centralize translation keys
  • Loading branch information
phoenixit99 authored Jan 16, 2025
2 parents 21ba797 + 81da98e commit 9e57c1c
Show file tree
Hide file tree
Showing 34 changed files with 1,061 additions and 426 deletions.
46 changes: 33 additions & 13 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,23 +21,31 @@ jobs:
echo "Code formatting issues detected. Run 'dart format .' and commit the changes.";
exit 1;
)
- name: Run Flutter Analyze
run: flutter analyze
- name: Generate Localization Files (Easy Localization)
- name: Generate Localization Files
id: gen_l10n
run: |
# Run the command to generate localization files and capture the output
output=$(flutter gen-l10n)
echo "$output"
# Check if there are untranslated messages in the output
if echo "$output" | grep -q "untranslated message"; then
echo "::error file=lib/l10n/l10n.yaml::Error: Untranslated messages detected in your localization files."
echo "::error::There are untranslated messages in the following languages:"
echo "$output" | grep "untranslated message"
echo "::error::Please ensure that all translations are provided in the respective .arb files."
exit 1
fi
- name: Check Localization Files
run: |
# Generate locale keys
dart run easy_localization:generate -f keys -o locale_keys.g.dart --source-dir=assets/translations --output-dir=lib/src/core/utils/gen/localization || (
echo "Error: Failed to generate locale keys.";
git diff --exit-code lib/l10n/ || (
echo "Localization files are outdated. Run 'flutter gen-l10n' and commit changes.";
exit 1;
)
- name: Run Dart Format and Check Localization Files Changes
- name: Check if translations_utils.dart has changes
run: |
# Run dart format without failing the step
dart format . || echo "dart format completed with warnings, but continuing pipeline."
# Check if there are changes in the localization files after generation
git diff --exit-code lib/src/core/utils/gen/localization || (
echo "Error: Localization files are outdated. Run the generation command and commit the changes.";
git diff --exit-code lib/src/core/utils/gen/localization/translations_utils.dart || (
echo "Error: Changes detected in translations_utils.dart. Please run the necessary custom translation utilities and commit changes.";
exit 1;
)
- name: Generate Assets Files
Expand All @@ -54,6 +62,18 @@ jobs:
echo "Error: Asset files are outdated. Run the generation command and commit the changes.";
exit 1;
)
- name: Run Flutter Analyze
run: flutter analyze
- name: Run Dart Format and Check Localization Files Changes
run: |
# Run dart format without failing the step
dart format . || echo "dart format completed with warnings, but continuing pipeline."
# Check if there are changes in the localization files after generation
git diff --exit-code lib/src/core/utils/gen/localization || (
echo "Error: Localization files are outdated. Run the generation command and commit the changes.";
exit 1;
)
- name: Run tests
run: flutter test
merge_check:
Expand Down
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
# 1.10.0+13

- [Update] : Replaced *.json translation files with *.arb and edited contents. [#60](https://github.com/pactus-project/pactus-gui/pull/60)

- [Chore] : Removed `easy_localization` from project dependencies. [#60](https://github.com/pactus-project/pactus-gui/pull/60)

- [Feat] : Added new structure for building translations and switching themes. [#60](https://github.com/pactus-project/pactus-gui/pull/60)

- [Update] : Updated `build_runner.sh` file for generating translation files. [#60](https://github.com/pactus-project/pactus-gui/pull/60)

# 1.10.0+12

- [Refactor] : Migrate styles to `pactus-gui-widgetbook` package for consistency and maintainability. [#56](https://github.com/pactus-project/pactus-gui/pull/56)
Expand Down
71 changes: 30 additions & 41 deletions build_runner.sh
Original file line number Diff line number Diff line change
@@ -1,62 +1,51 @@
#!/bin/bash

# Welcome message
# Displaying a welcome message to the user
echo "Welcome to the Build Runner Wizard!"

# Display options to the user
# Showing the available options to the user
echo "Please select an option:"
echo "1. Automatic Execution"
echo "2. Manual Execution"
echo "3. Re-Build Translation Files"
echo "4. Re-Generate Asset Files"
echo "2. Re-Generate Asset Files"

# Read user input
read -p "Enter your choice (1, 2, 3, or 4): " choice
# Reading the user's input for their choice
read -p "Enter your choice (1 or 2): " choice

# Check selected option and execute corresponding commands
# Handling the user's choice with a case statement
case $choice in
1)
# User selected Automatic Execution
echo "* You selected Automatic Execution."
# Automatic execution

# Rebuild translation files
dart run easy_localization:generate --source-dir=assets/translations --output-dir=lib/src/core/utils/gen/localization
dart run easy_localization:generate -f keys -o locale_keys.g.dart --source-dir=assets/translations --output-dir=lib/src/core/utils/gen/localization
dart run build_runner build --delete-conflicting-outputs --build-filter="lib\src\core\constants\localization\*.dart"
# Step 1: Rebuilding translation files using the l10n package
# This command generates localization files from ARB files located in assets/translations.
flutter gen-l10n --output-dir=lib/l10n --arb-dir=lib/l10n

# Execute automatic build runner command
# Step 2: Running custom translation utilities
# Executes the custom logic defined in translations_utils.dart (used for post-processing translations if needed).
echo "* Running custom translations utilities from lib/src/core/utils/gen/localization/translations_utils.dart"
dart lib/src/core/utils/gen/localization/translations_utils.dart

# Step 3: Running build_runner to generate code for localization and other assets
# This builds the project and deletes any conflicting outputs that may cause issues.
dart run build_runner build --delete-conflicting-outputs

# Step 4: flutter pub get for update l10n dependency
flutter pub get
;;
2)
echo "* You selected Manual Execution."
# Read user input text
read -p "Enter your text (comma-separated list for multiple items): " text

# Convert input text to an array using ',' as a delimiter
IFS=',' read -r -a text_array <<< "$text"

# Loop through each item in the array and execute the command
for item in "${text_array[@]}"
do
# Replace '/' with '\' in the input text
text_with_backslashes=$(echo "$item" | sed 's/\//\\/g')
# Replace the desired text in the command and execute it
dart run build_runner build --delete-conflicting-outputs --build-filter="$text_with_backslashes\*.dart"
done
;;
3)
echo "* You selected Re-Build Translation Files."
# Execute commands for rebuilding translation files
dart run easy_localization:generate --source-dir=assets/translations --output-dir=lib/src/core/utils/gen/localization
dart run easy_localization:generate -f keys -o locale_keys.g.dart --source-dir=assets/translations --output-dir=lib/src/core/utils/gen/localization
dart run build_runner build --delete-conflicting-outputs --build-filter="lib\src\core\constants\localization\*.dart"
;;
4)
# User selected Re-Generate Asset Files
echo "* You selected Re-Generate Asset Files."
# Execute commands for rebuilding asset files
dart run build_runner build --delete-conflicting-outputs --build-filter="lib\src\core\utils\gen\assets\*.dart"

# Re-running build_runner to regenerate asset files
# This specifically handles assets located in the 'assets' folder.
dart run build_runner build --delete-conflicting-outputs --build-filter="lib/src/core/utils/gen/assets\*.dart"
;;
*)
echo "* Invalid choice. Please enter 1, 2, 3, or 4."
# Invalid choice entered by the user
echo "* Invalid choice. Please enter 1 or 2"
;;
esac

# Pausing for 3 seconds before exiting to give the user a chance to read the output
sleep 3s ;
5 changes: 3 additions & 2 deletions assets/translations/en.json → lib/l10n/app_en.arb
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
{
"title": "Hello, World!",
"@@locale": "en",
"title": "Hello, World !",
"subtitle": "Welcome to Localization",
"description": "You have pushed the button this many times:",
"switch_language": "Switch language",
"applications": "Applications"
}
}
6 changes: 3 additions & 3 deletions assets/translations/es.json → lib/l10n/app_es.arb
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"title": "¡Hola, Mundo!",
"@@locale": "es",
"title": "¡Hola, Mundo !",
"subtitle": "Bienvenido a Localización",
"description": "Has pulsado el botón tantas veces:",
"switchLanguage": "Cambiar idioma",
"switch_language": "Cambiar idioma",
"applications": "Applications"

}
5 changes: 3 additions & 2 deletions assets/translations/fr.json → lib/l10n/app_fr.arb
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
{
"title": "Bonjour",
"@@locale": "fr",
"title": "Bonjour le monde !",
"subtitle": "Bienvenue dans Localisation",
"description": "Vous avez appuyé sur le bouton autant de fois :",
"switchLanguage": "Changer de langue",
"switch_language": "Changer de langue",
"applications": "Applications"
}
83 changes: 45 additions & 38 deletions lib/main.dart
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:fluent_ui/fluent_ui.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:gui/src/core/constants/configurations.dart';
import 'package:gui/src/core/router/app_router.dart';
import 'package:gui/src/core/utils/gen/localization/codegen_loader.g.dart';
import 'package:gui/src/features/main/language/core/language_constants.dart';
import 'package:gui/src/features/main/theme/bloc/theme_bloc.dart';
import 'package:pactus_gui_widgetbook/app_styles.dart';
import 'src/features/main/language/presentation/bloc/language_bloc.dart';

void main() async {
await EasyLocalization.ensureInitialized();
void main() {
runApp(
MultiBlocProvider(
providers: [
BlocProvider<LanguageBloc>(
create: (_) => LanguageBloc(),
),
BlocProvider<ThemeBloc>(
create: (_) => ThemeBloc(),
BlocProvider<AppThemeCubit>(
create: (_) => AppThemeCubit(),
),
],
child: PactusGuiApp(),
Expand All @@ -30,38 +30,45 @@ class PactusGuiApp extends StatelessWidget {

@override
Widget build(BuildContext context) {
return EasyLocalization(
useFallbackTranslations: true,
supportedLocales: AppConfigs.supportedLocales,
path: AppConfigs.translationsPath,
fallbackLocale: AppConfigs.enLocale,
startLocale: AppConfigs.enLocale,
assetLoader: const CodegenLoader(),
child: BlocBuilder<LanguageBloc, LanguageState>(
builder: (context, languageState) {
return BlocBuilder<ThemeBloc, ThemeState>(
builder: (context, themeState) {
return FluentApp.router(
debugShowCheckedModeBanner: false,
routerConfig: routerConfig,
title: 'Pactus Gui App',
theme: FluentThemeData.light().copyWith(
extensions: AppThemeData.lightExtensions,
typography: AppThemeData.typography,
),
themeMode: themeState.themeMode,
darkTheme: FluentThemeData.dark().copyWith(
extensions: AppThemeData.darkExtensions,
typography: AppThemeData.typography,
),
localizationsDelegates: context.localizationDelegates,
supportedLocales: AppConfigs.supportedLocales,
locale: languageState.selectedLanguage.value,
);
},
);
},
),
return BlocBuilder<LanguageBloc, LanguageState>(
builder: (context, languageState) {
return BlocBuilder<AppThemeCubit, bool>(
builder: (context, isDarkMode) {
final theme = isDarkMode
? AppThemeData.darkTheme().copyWith(
extensions: AppThemeData.darkExtensions,
typography: AppThemeData.typography,
)
: AppThemeData.lightTheme().copyWith(
extensions: AppThemeData.lightExtensions,
typography: AppThemeData.typography,
);
return FluentApp.router(
debugShowCheckedModeBanner: false,
routerConfig: routerConfig,
title: 'Pactus Gui App',
themeMode: isDarkMode ? ThemeMode.dark : ThemeMode.light,
theme: theme,
localizationsDelegates: [
AppLocalizations.delegate,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
supportedLocales: AppConfigs.supportedLocales,
locale: languageState.selectedLanguage == null
? Locale(
LanguageConstants.enUS.language,
LanguageConstants.enUS.country,
)
: Locale(
languageState.selectedLanguage!.language,
languageState.selectedLanguage!.country,
),
);
},
);
},
);
}
}
16 changes: 0 additions & 16 deletions lib/presentation/bloc/language_bloc/language_bloc.dart

This file was deleted.

21 changes: 8 additions & 13 deletions lib/src/core/common/widgets/theme_switcher.dart
Original file line number Diff line number Diff line change
Expand Up @@ -42,18 +42,17 @@ class ThemeSwitcher extends StatelessWidget {

@override
Widget build(BuildContext context) {
return BlocBuilder<ThemeBloc, ThemeState>(
builder: (context, themeState) {
return BlocBuilder<AppThemeCubit, bool>(
builder: (context, isDarkTheme) {
const duration = Duration(milliseconds: 200);
final isLightTheme = themeState.themeMode == ThemeMode.light;

return Row(
mainAxisSize: MainAxisSize.min,
children: [
// Dark mode icon
AnimatedOpacity(
curve: Curves.easeIn,
opacity: isLightTheme ? 0.0 : 1.0,
opacity: isDarkTheme ? 1.0 : 0.0,
duration: duration,
child: SvgPicture.asset(
Assets.icons.icLightMode,
Expand All @@ -62,11 +61,7 @@ class ThemeSwitcher extends StatelessWidget {
// Switch
GestureDetector(
onTap: () {
context.read<ThemeBloc>().add(
ThemeChanged(
theme: isLightTheme ? ThemeMode.dark : ThemeMode.light,
),
);
context.read<AppThemeCubit>().toggleTheme();
},
child: AnimatedContainer(
margin: const EdgeInsets.symmetric(horizontal: 4),
Expand All @@ -84,9 +79,9 @@ class ThemeSwitcher extends StatelessWidget {
padding: const EdgeInsets.symmetric(horizontal: 3),
child: AnimatedAlign(
duration: const Duration(milliseconds: 100),
alignment: isLightTheme
? Alignment.centerRight
: Alignment.centerLeft,
alignment: isDarkTheme
? Alignment.centerLeft
: Alignment.centerRight,
child: Container(
width: 14,
height: 14,
Expand All @@ -102,7 +97,7 @@ class ThemeSwitcher extends StatelessWidget {
// Light mode icon
AnimatedOpacity(
curve: Curves.easeIn,
opacity: isLightTheme ? 1.0 : 0.0,
opacity: isDarkTheme ? 0.0 : 1.0,
duration: duration,
child: SvgPicture.asset(
Assets.icons.icDarkMode,
Expand Down
Loading

0 comments on commit 9e57c1c

Please sign in to comment.