Added translations library

This commit is contained in:
Juan Gilsanz Polo
2024-02-22 00:52:07 +01:00
parent 658adb7e2c
commit 3fd32ca5fa
13 changed files with 571 additions and 88 deletions

252
lib/i18n/strings.g.dart Normal file
View File

@@ -0,0 +1,252 @@
/// Generated file. Do not edit.
///
/// Original: lib/i18n
/// To regenerate, run: `dart run slang`
///
/// Locales: 2
/// Strings: 8 (4 per locale)
///
/// Built on 2024-02-21 at 23:50 UTC
// coverage:ignore-file
// ignore_for_file: type=lint
import 'package:flutter/widgets.dart';
import 'package:slang/builder/model/node.dart';
import 'package:slang_flutter/slang_flutter.dart';
export 'package:slang_flutter/slang_flutter.dart';
const AppLocale _baseLocale = AppLocale.en;
/// Supported locales, see extension methods below.
///
/// Usage:
/// - LocaleSettings.setLocale(AppLocale.en) // set locale
/// - Locale locale = AppLocale.en.flutterLocale // get flutter locale from enum
/// - if (LocaleSettings.currentLocale == AppLocale.en) // locale check
enum AppLocale with BaseAppLocale<AppLocale, Translations> {
en(languageCode: 'en', build: Translations.build),
es(languageCode: 'es', build: _StringsEs.build);
const AppLocale({required this.languageCode, this.scriptCode, this.countryCode, required this.build}); // ignore: unused_element
@override final String languageCode;
@override final String? scriptCode;
@override final String? countryCode;
@override final TranslationBuilder<AppLocale, Translations> build;
/// Gets current instance managed by [LocaleSettings].
Translations get translations => LocaleSettings.instance.translationMap[this]!;
}
/// Method A: Simple
///
/// No rebuild after locale change.
/// Translation happens during initialization of the widget (call of t).
/// Configurable via 'translate_var'.
///
/// Usage:
/// String a = t.someKey.anotherKey;
/// String b = t['someKey.anotherKey']; // Only for edge cases!
Translations get t => LocaleSettings.instance.currentTranslations;
/// Method B: Advanced
///
/// All widgets using this method will trigger a rebuild when locale changes.
/// Use this if you have e.g. a settings page where the user can select the locale during runtime.
///
/// Step 1:
/// wrap your App with
/// TranslationProvider(
/// child: MyApp()
/// );
///
/// Step 2:
/// final t = Translations.of(context); // Get t variable.
/// String a = t.someKey.anotherKey; // Use t variable.
/// String b = t['someKey.anotherKey']; // Only for edge cases!
class TranslationProvider extends BaseTranslationProvider<AppLocale, Translations> {
TranslationProvider({required super.child}) : super(settings: LocaleSettings.instance);
static InheritedLocaleData<AppLocale, Translations> of(BuildContext context) => InheritedLocaleData.of<AppLocale, Translations>(context);
}
/// Method B shorthand via [BuildContext] extension method.
/// Configurable via 'translate_var'.
///
/// Usage (e.g. in a widget's build method):
/// context.t.someKey.anotherKey
extension BuildContextTranslationsExtension on BuildContext {
Translations get t => TranslationProvider.of(this).translations;
}
/// Manages all translation instances and the current locale
class LocaleSettings extends BaseFlutterLocaleSettings<AppLocale, Translations> {
LocaleSettings._() : super(utils: AppLocaleUtils.instance);
static final instance = LocaleSettings._();
// static aliases (checkout base methods for documentation)
static AppLocale get currentLocale => instance.currentLocale;
static Stream<AppLocale> getLocaleStream() => instance.getLocaleStream();
static AppLocale setLocale(AppLocale locale, {bool? listenToDeviceLocale = false}) => instance.setLocale(locale, listenToDeviceLocale: listenToDeviceLocale);
static AppLocale setLocaleRaw(String rawLocale, {bool? listenToDeviceLocale = false}) => instance.setLocaleRaw(rawLocale, listenToDeviceLocale: listenToDeviceLocale);
static AppLocale useDeviceLocale() => instance.useDeviceLocale();
@Deprecated('Use [AppLocaleUtils.supportedLocales]') static List<Locale> get supportedLocales => instance.supportedLocales;
@Deprecated('Use [AppLocaleUtils.supportedLocalesRaw]') static List<String> get supportedLocalesRaw => instance.supportedLocalesRaw;
static void setPluralResolver({String? language, AppLocale? locale, PluralResolver? cardinalResolver, PluralResolver? ordinalResolver}) => instance.setPluralResolver(
language: language,
locale: locale,
cardinalResolver: cardinalResolver,
ordinalResolver: ordinalResolver,
);
}
/// Provides utility functions without any side effects.
class AppLocaleUtils extends BaseAppLocaleUtils<AppLocale, Translations> {
AppLocaleUtils._() : super(baseLocale: _baseLocale, locales: AppLocale.values);
static final instance = AppLocaleUtils._();
// static aliases (checkout base methods for documentation)
static AppLocale parse(String rawLocale) => instance.parse(rawLocale);
static AppLocale parseLocaleParts({required String languageCode, String? scriptCode, String? countryCode}) => instance.parseLocaleParts(languageCode: languageCode, scriptCode: scriptCode, countryCode: countryCode);
static AppLocale findDeviceLocale() => instance.findDeviceLocale();
static List<Locale> get supportedLocales => instance.supportedLocales;
static List<String> get supportedLocalesRaw => instance.supportedLocalesRaw;
}
// translations
// Path: <root>
class Translations implements BaseTranslations<AppLocale, Translations> {
/// Returns the current translations of the given [context].
///
/// Usage:
/// final t = Translations.of(context);
static Translations of(BuildContext context) => InheritedLocaleData.of<AppLocale, Translations>(context).translations;
/// You can call this constructor and build your own translation instance of this locale.
/// Constructing via the enum [AppLocale.build] is preferred.
Translations.build({Map<String, Node>? overrides, PluralResolver? cardinalResolver, PluralResolver? ordinalResolver})
: assert(overrides == null, 'Set "translation_overrides: true" in order to enable this feature.'),
$meta = TranslationMetadata(
locale: AppLocale.en,
overrides: overrides ?? {},
cardinalResolver: cardinalResolver,
ordinalResolver: ordinalResolver,
) {
$meta.setFlatMapFunction(_flatMapFunction);
}
/// Metadata for the translations of <en>.
@override final TranslationMetadata<AppLocale, Translations> $meta;
/// Access flat map
dynamic operator[](String key) => $meta.getTranslation(key);
late final Translations _root = this; // ignore: unused_field
// Translations
late final _StringsConnectEn connect = _StringsConnectEn._(_root);
late final _StringsLinksEn links = _StringsLinksEn._(_root);
}
// Path: connect
class _StringsConnectEn {
_StringsConnectEn._(this._root);
final Translations _root; // ignore: unused_field
// Translations
String get connect => 'Connect';
String get connecting => 'Connecting...';
String get cannotConnectToServer => 'Cannot connect to the server.';
}
// Path: links
class _StringsLinksEn {
_StringsLinksEn._(this._root);
final Translations _root; // ignore: unused_field
// Translations
String get links => 'Links';
}
// Path: <root>
class _StringsEs implements Translations {
/// You can call this constructor and build your own translation instance of this locale.
/// Constructing via the enum [AppLocale.build] is preferred.
_StringsEs.build({Map<String, Node>? overrides, PluralResolver? cardinalResolver, PluralResolver? ordinalResolver})
: assert(overrides == null, 'Set "translation_overrides: true" in order to enable this feature.'),
$meta = TranslationMetadata(
locale: AppLocale.es,
overrides: overrides ?? {},
cardinalResolver: cardinalResolver,
ordinalResolver: ordinalResolver,
) {
$meta.setFlatMapFunction(_flatMapFunction);
}
/// Metadata for the translations of <es>.
@override final TranslationMetadata<AppLocale, Translations> $meta;
/// Access flat map
@override dynamic operator[](String key) => $meta.getTranslation(key);
@override late final _StringsEs _root = this; // ignore: unused_field
// Translations
@override late final _StringsConnectEs connect = _StringsConnectEs._(_root);
@override late final _StringsLinksEs links = _StringsLinksEs._(_root);
}
// Path: connect
class _StringsConnectEs implements _StringsConnectEn {
_StringsConnectEs._(this._root);
@override final _StringsEs _root; // ignore: unused_field
// Translations
@override String get connect => 'Conectar';
@override String get connecting => 'Conectando...';
@override String get cannotConnectToServer => 'No se puede conectar con el servidor.';
}
// Path: links
class _StringsLinksEs implements _StringsLinksEn {
_StringsLinksEs._(this._root);
@override final _StringsEs _root; // ignore: unused_field
// Translations
@override String get links => 'Enlaces';
}
/// Flat map(s) containing all translations.
/// Only for edge cases! For simple maps, use the map function of this library.
extension on Translations {
dynamic _flatMapFunction(String path) {
switch (path) {
case 'connect.connect': return 'Connect';
case 'connect.connecting': return 'Connecting...';
case 'connect.cannotConnectToServer': return 'Cannot connect to the server.';
case 'links.links': return 'Links';
default: return null;
}
}
}
extension on _StringsEs {
dynamic _flatMapFunction(String path) {
switch (path) {
case 'connect.connect': return 'Conectar';
case 'connect.connecting': return 'Conectando...';
case 'connect.cannotConnectToServer': return 'No se puede conectar con el servidor.';
case 'links.links': return 'Enlaces';
default: return null;
}
}
}

View File

@@ -0,0 +1,10 @@
{
"connect": {
"connect": "Connect",
"connecting": "Connecting...",
"cannotConnectToServer": "Cannot connect to the server."
},
"links": {
"links": "Links"
}
}

View File

@@ -0,0 +1,10 @@
{
"connect": {
"connect": "Conectar",
"connecting": "Conectando...",
"cannotConnectToServer": "No se puede conectar con el servidor."
},
"links": {
"links": "Enlaces"
}
}

View File

@@ -2,31 +2,37 @@ import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:my_linkding/constants/global_keys.dart';
import 'package:dynamic_color/dynamic_color.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:my_linkding/config/theme.dart';
import 'package:my_linkding/constants/colors.dart';
import 'package:my_linkding/i18n/strings.g.dart';
import 'package:my_linkding/providers/router_provider.dart';
import 'package:my_linkding/providers/shared_preferences_provider.dart';
import 'package:my_linkding/utils/http_overrides.dart';
import 'package:shared_preferences/shared_preferences.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge);
LocaleSettings.useDeviceLocale();
HttpOverrides.global = MyHttpOverrides();
final sharedPreferences = await SharedPreferences.getInstance();
runApp(
ProviderScope(
overrides: [
sharedPreferencesProvider.overrideWithValue(sharedPreferences),
],
child: const MyApp(),
TranslationProvider(
child: ProviderScope(
overrides: [
sharedPreferencesProvider.overrideWithValue(sharedPreferences),
],
child: const MyApp(),
),
),
);
}
@@ -41,6 +47,9 @@ class MyApp extends ConsumerWidget {
title: 'My Linkding',
theme: lightDynamic != null ? lightTheme(lightDynamic) : lightThemeOldVersions(colors[0]),
darkTheme: darkDynamic != null ? darkTheme(darkDynamic) : darkThemeOldVersions(colors[0]),
locale: TranslationProvider.of(context).flutterLocale,
supportedLocales: AppLocaleUtils.supportedLocales,
localizationsDelegates: GlobalMaterialLocalizations.delegates,
debugShowCheckedModeBanner: false,
scaffoldMessengerKey: scaffoldMessengerGlobalKey,
routerConfig: ref.watch(routerProvider),

View File

@@ -1,15 +1,13 @@
import 'package:flutter/material.dart';
import 'package:my_linkding/providers/shared_preferences_provider.dart';
import 'package:uuid/uuid.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'package:my_linkding/screens/connect/model/connect_model.dart';
import 'package:my_linkding/providers/server_instances_provider.dart';
import 'package:my_linkding/i18n/strings.g.dart';
import 'package:my_linkding/constants/enums.dart';
import 'package:my_linkding/utils/process_modal.dart';
import 'package:my_linkding/providers/router_provider.dart';
import 'package:my_linkding/router/paths.dart';
import 'package:my_linkding/utils/snackbar.dart';
import 'package:my_linkding/models/server_instance.dart';
import 'package:my_linkding/providers/api_client_provider.dart';
@@ -89,7 +87,7 @@ FutureOr<bool> connectToServer(ConnectToServerRef ref) async {
final apiClient = ApiClient(serverInstance: serverInstance);
final processModal = ProcessModal();
processModal.open("Connecting...");
processModal.open(t.connect.connecting);
final result = await apiClient.checkConnectionInstance();
@@ -99,7 +97,7 @@ FutureOr<bool> connectToServer(ConnectToServerRef ref) async {
ref.read(serverInstancesProvider.notifier).saveNewInstance(serverInstance);
// ref.watch(routerProvider).replace(RoutesPaths.links);
} else {
showSnacbkar(label: "Invalida auth", color: Colors.red);
showSnacbkar(label: t.connect.cannotConnectToServer, color: Colors.red);
}
return false;

View File

@@ -1,5 +1,7 @@
import 'package:flutter/material.dart';
import 'package:my_linkding/i18n/strings.g.dart';
class Links extends StatelessWidget {
const Links({Key? key}) : super(key: key);
@@ -16,7 +18,7 @@ class Links extends StatelessWidget {
floating: true,
centerTitle: false,
forceElevated: innerBoxIsScrolled,
title: Text("Links"),
title: Text(t.links.links),
),
),
],