diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist
index 089d44c..7fcc9e8 100644
--- a/ios/Runner/Info.plist
+++ b/ios/Runner/Info.plist
@@ -1,49 +1,54 @@
-
- CFBundleDevelopmentRegion
- $(DEVELOPMENT_LANGUAGE)
- CFBundleDisplayName
- My Linkding
- CFBundleExecutable
- $(EXECUTABLE_NAME)
- CFBundleIdentifier
- $(PRODUCT_BUNDLE_IDENTIFIER)
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleName
- my_linkding
- CFBundlePackageType
- APPL
- CFBundleShortVersionString
- $(FLUTTER_BUILD_NAME)
- CFBundleSignature
- ????
- CFBundleVersion
- $(FLUTTER_BUILD_NUMBER)
- LSRequiresIPhoneOS
-
- UILaunchStoryboardName
- LaunchScreen
- UIMainStoryboardFile
- Main
- UISupportedInterfaceOrientations
-
- UIInterfaceOrientationPortrait
- UIInterfaceOrientationLandscapeLeft
- UIInterfaceOrientationLandscapeRight
-
- UISupportedInterfaceOrientations~ipad
-
- UIInterfaceOrientationPortrait
- UIInterfaceOrientationPortraitUpsideDown
- UIInterfaceOrientationLandscapeLeft
- UIInterfaceOrientationLandscapeRight
-
- CADisableMinimumFrameDurationOnPhone
-
- UIApplicationSupportsIndirectInputEvents
-
-
-
+
+ CFBundleDevelopmentRegion
+ $(DEVELOPMENT_LANGUAGE)
+ CFBundleDisplayName
+ My Linkding
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIdentifier
+ $(PRODUCT_BUNDLE_IDENTIFIER)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ my_linkding
+ CFBundlePackageType
+ APPL
+ CFBundleShortVersionString
+ $(FLUTTER_BUILD_NAME)
+ CFBundleSignature
+ ????
+ CFBundleVersion
+ $(FLUTTER_BUILD_NUMBER)
+ LSRequiresIPhoneOS
+
+ UILaunchStoryboardName
+ LaunchScreen
+ UIMainStoryboardFile
+ Main
+ UISupportedInterfaceOrientations
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+ UISupportedInterfaceOrientations~ipad
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationPortraitUpsideDown
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+ CADisableMinimumFrameDurationOnPhone
+
+ UIApplicationSupportsIndirectInputEvents
+
+ CFBundleLocalizations
+
+ en
+ es
+
+
+
\ No newline at end of file
diff --git a/lib/i18n/strings.g.dart b/lib/i18n/strings.g.dart
new file mode 100644
index 0000000..9b2692a
--- /dev/null
+++ b/lib/i18n/strings.g.dart
@@ -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 {
+ 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 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 {
+ TranslationProvider({required super.child}) : super(settings: LocaleSettings.instance);
+
+ static InheritedLocaleData of(BuildContext context) => InheritedLocaleData.of(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 {
+ LocaleSettings._() : super(utils: AppLocaleUtils.instance);
+
+ static final instance = LocaleSettings._();
+
+ // static aliases (checkout base methods for documentation)
+ static AppLocale get currentLocale => instance.currentLocale;
+ static Stream 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 get supportedLocales => instance.supportedLocales;
+ @Deprecated('Use [AppLocaleUtils.supportedLocalesRaw]') static List 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 {
+ 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 get supportedLocales => instance.supportedLocales;
+ static List get supportedLocalesRaw => instance.supportedLocalesRaw;
+}
+
+// translations
+
+// Path:
+class Translations implements BaseTranslations {
+ /// Returns the current translations of the given [context].
+ ///
+ /// Usage:
+ /// final t = Translations.of(context);
+ static Translations of(BuildContext context) => InheritedLocaleData.of(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? 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 .
+ @override final TranslationMetadata $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:
+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? 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 .
+ @override final TranslationMetadata $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;
+ }
+ }
+}
diff --git a/lib/i18n/strings_en.i18n.json b/lib/i18n/strings_en.i18n.json
new file mode 100644
index 0000000..92b6646
--- /dev/null
+++ b/lib/i18n/strings_en.i18n.json
@@ -0,0 +1,10 @@
+{
+ "connect": {
+ "connect": "Connect",
+ "connecting": "Connecting...",
+ "cannotConnectToServer": "Cannot connect to the server."
+ },
+ "links": {
+ "links": "Links"
+ }
+}
\ No newline at end of file
diff --git a/lib/i18n/strings_es.i18n.json b/lib/i18n/strings_es.i18n.json
new file mode 100644
index 0000000..12a0edc
--- /dev/null
+++ b/lib/i18n/strings_es.i18n.json
@@ -0,0 +1,10 @@
+{
+ "connect": {
+ "connect": "Conectar",
+ "connecting": "Conectando...",
+ "cannotConnectToServer": "No se puede conectar con el servidor."
+ },
+ "links": {
+ "links": "Enlaces"
+ }
+}
\ No newline at end of file
diff --git a/lib/main.dart b/lib/main.dart
index fb86979..8ae3c29 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -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),
diff --git a/lib/screens/connect/provider/connect_provider.dart b/lib/screens/connect/provider/connect_provider.dart
index 28df05f..9ed2ca9 100644
--- a/lib/screens/connect/provider/connect_provider.dart
+++ b/lib/screens/connect/provider/connect_provider.dart
@@ -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 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 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;
diff --git a/lib/screens/links/ui/links.dart b/lib/screens/links/ui/links.dart
index 7a04800..6b4cafb 100644
--- a/lib/screens/links/ui/links.dart
+++ b/lib/screens/links/ui/links.dart
@@ -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),
),
),
],
diff --git a/macos/Podfile.lock b/macos/Podfile.lock
new file mode 100644
index 0000000..933b4d2
--- /dev/null
+++ b/macos/Podfile.lock
@@ -0,0 +1,35 @@
+PODS:
+ - dynamic_color (0.0.2):
+ - FlutterMacOS
+ - FlutterMacOS (1.0.0)
+ - shared_preferences_foundation (0.0.1):
+ - Flutter
+ - FlutterMacOS
+ - url_launcher_macos (0.0.1):
+ - FlutterMacOS
+
+DEPENDENCIES:
+ - dynamic_color (from `Flutter/ephemeral/.symlinks/plugins/dynamic_color/macos`)
+ - FlutterMacOS (from `Flutter/ephemeral`)
+ - shared_preferences_foundation (from `Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin`)
+ - url_launcher_macos (from `Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos`)
+
+EXTERNAL SOURCES:
+ dynamic_color:
+ :path: Flutter/ephemeral/.symlinks/plugins/dynamic_color/macos
+ FlutterMacOS:
+ :path: Flutter/ephemeral
+ shared_preferences_foundation:
+ :path: Flutter/ephemeral/.symlinks/plugins/shared_preferences_foundation/darwin
+ url_launcher_macos:
+ :path: Flutter/ephemeral/.symlinks/plugins/url_launcher_macos/macos
+
+SPEC CHECKSUMS:
+ dynamic_color: 2eaa27267de1ca20d879fbd6e01259773fb1670f
+ FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24
+ shared_preferences_foundation: b4c3b4cddf1c21f02770737f147a3f5da9d39695
+ url_launcher_macos: d2691c7dd33ed713bf3544850a623080ec693d95
+
+PODFILE CHECKSUM: 236401fc2c932af29a9fcf0e97baeeb2d750d367
+
+COCOAPODS: 1.14.3
diff --git a/macos/Runner.xcodeproj/project.pbxproj b/macos/Runner.xcodeproj/project.pbxproj
index f0924c4..1d69237 100644
--- a/macos/Runner.xcodeproj/project.pbxproj
+++ b/macos/Runner.xcodeproj/project.pbxproj
@@ -21,12 +21,14 @@
/* End PBXAggregateTarget section */
/* Begin PBXBuildFile section */
+ 2C82BC3BDC8F3538F3565F25 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D782E92928080117BE6339AE /* Pods_RunnerTests.framework */; };
331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C80D7294CF71000263BE5 /* RunnerTests.swift */; };
335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; };
33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; };
33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; };
33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; };
33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; };
+ D0434BDC47844E5C89663A09 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1FB5A738B70ED51CEAACDF2C /* Pods_Runner.framework */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@@ -60,11 +62,13 @@
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
+ 14E0069015837F24128F4C80 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; };
+ 1FB5A738B70ED51CEAACDF2C /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
331C80D5294CF71000263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
331C80D7294CF71000263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; };
333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; };
335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = ""; };
- 33CC10ED2044A3C60003C045 /* my_linkding.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "my_linkding.app"; sourceTree = BUILT_PRODUCTS_DIR; };
+ 33CC10ED2044A3C60003C045 /* my_linkding.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = my_linkding.app; sourceTree = BUILT_PRODUCTS_DIR; };
33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = ""; };
33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; };
@@ -78,6 +82,12 @@
33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; };
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; };
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; };
+ 9CB4A68230725B1605ABB9B5 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; };
+ AE76C16CF7FD949F1C440D8D /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; };
+ B0CB230F5A87B345D7B8FAE9 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; };
+ D782E92928080117BE6339AE /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+ E92A18855CB6A3A7F902F028 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; };
+ FD6AFD021F96A1F86691E750 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -85,6 +95,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
+ 2C82BC3BDC8F3538F3565F25 /* Pods_RunnerTests.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -92,12 +103,27 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
+ D0434BDC47844E5C89663A09 /* Pods_Runner.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
+ 1B4525708D1C7A1890544101 /* Pods */ = {
+ isa = PBXGroup;
+ children = (
+ FD6AFD021F96A1F86691E750 /* Pods-Runner.debug.xcconfig */,
+ AE76C16CF7FD949F1C440D8D /* Pods-Runner.release.xcconfig */,
+ E92A18855CB6A3A7F902F028 /* Pods-Runner.profile.xcconfig */,
+ 14E0069015837F24128F4C80 /* Pods-RunnerTests.debug.xcconfig */,
+ B0CB230F5A87B345D7B8FAE9 /* Pods-RunnerTests.release.xcconfig */,
+ 9CB4A68230725B1605ABB9B5 /* Pods-RunnerTests.profile.xcconfig */,
+ );
+ name = Pods;
+ path = Pods;
+ sourceTree = "";
+ };
331C80D6294CF71000263BE5 /* RunnerTests */ = {
isa = PBXGroup;
children = (
@@ -125,6 +151,7 @@
331C80D6294CF71000263BE5 /* RunnerTests */,
33CC10EE2044A3C60003C045 /* Products */,
D73912EC22F37F3D000D13A0 /* Frameworks */,
+ 1B4525708D1C7A1890544101 /* Pods */,
);
sourceTree = "";
};
@@ -175,6 +202,8 @@
D73912EC22F37F3D000D13A0 /* Frameworks */ = {
isa = PBXGroup;
children = (
+ 1FB5A738B70ED51CEAACDF2C /* Pods_Runner.framework */,
+ D782E92928080117BE6339AE /* Pods_RunnerTests.framework */,
);
name = Frameworks;
sourceTree = "";
@@ -186,6 +215,7 @@
isa = PBXNativeTarget;
buildConfigurationList = 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */;
buildPhases = (
+ FA7823E03E9207CB76E87418 /* [CP] Check Pods Manifest.lock */,
331C80D1294CF70F00263BE5 /* Sources */,
331C80D2294CF70F00263BE5 /* Frameworks */,
331C80D3294CF70F00263BE5 /* Resources */,
@@ -204,11 +234,13 @@
isa = PBXNativeTarget;
buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */;
buildPhases = (
+ 654118FCF78DD717EBFB00E0 /* [CP] Check Pods Manifest.lock */,
33CC10E92044A3C60003C045 /* Sources */,
33CC10EA2044A3C60003C045 /* Frameworks */,
33CC10EB2044A3C60003C045 /* Resources */,
33CC110E2044A8840003C045 /* Bundle Framework */,
3399D490228B24CF009A79C7 /* ShellScript */,
+ D41BC943399F1ACBD0C0AA49 /* [CP] Embed Pods Frameworks */,
);
buildRules = (
);
@@ -328,6 +360,67 @@
shellPath = /bin/sh;
shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire";
};
+ 654118FCF78DD717EBFB00E0 /* [CP] Check Pods Manifest.lock */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputFileListPaths = (
+ );
+ inputPaths = (
+ "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
+ "${PODS_ROOT}/Manifest.lock",
+ );
+ name = "[CP] Check Pods Manifest.lock";
+ outputFileListPaths = (
+ );
+ outputPaths = (
+ "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
+ showEnvVarsInLog = 0;
+ };
+ D41BC943399F1ACBD0C0AA49 /* [CP] Embed Pods Frameworks */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputFileListPaths = (
+ "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
+ );
+ name = "[CP] Embed Pods Frameworks";
+ outputFileListPaths = (
+ "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
+ showEnvVarsInLog = 0;
+ };
+ FA7823E03E9207CB76E87418 /* [CP] Check Pods Manifest.lock */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputFileListPaths = (
+ );
+ inputPaths = (
+ "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
+ "${PODS_ROOT}/Manifest.lock",
+ );
+ name = "[CP] Check Pods Manifest.lock";
+ outputFileListPaths = (
+ );
+ outputPaths = (
+ "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt",
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
+ showEnvVarsInLog = 0;
+ };
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
@@ -379,6 +472,7 @@
/* Begin XCBuildConfiguration section */
331C80DB294CF71000263BE5 /* Debug */ = {
isa = XCBuildConfiguration;
+ baseConfigurationReference = 14E0069015837F24128F4C80 /* Pods-RunnerTests.debug.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CURRENT_PROJECT_VERSION = 1;
@@ -393,6 +487,7 @@
};
331C80DC294CF71000263BE5 /* Release */ = {
isa = XCBuildConfiguration;
+ baseConfigurationReference = B0CB230F5A87B345D7B8FAE9 /* Pods-RunnerTests.release.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CURRENT_PROJECT_VERSION = 1;
@@ -407,6 +502,7 @@
};
331C80DD294CF71000263BE5 /* Profile */ = {
isa = XCBuildConfiguration;
+ baseConfigurationReference = 9CB4A68230725B1605ABB9B5 /* Pods-RunnerTests.profile.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CURRENT_PROJECT_VERSION = 1;
diff --git a/macos/Runner.xcworkspace/contents.xcworkspacedata b/macos/Runner.xcworkspace/contents.xcworkspacedata
index 1d526a1..21a3cc1 100644
--- a/macos/Runner.xcworkspace/contents.xcworkspacedata
+++ b/macos/Runner.xcworkspace/contents.xcworkspacedata
@@ -4,4 +4,7 @@
+
+
diff --git a/macos/Runner/Info.plist b/macos/Runner/Info.plist
index 4789daa..1e4a2cb 100644
--- a/macos/Runner/Info.plist
+++ b/macos/Runner/Info.plist
@@ -1,32 +1,37 @@
-
- CFBundleDevelopmentRegion
- $(DEVELOPMENT_LANGUAGE)
- CFBundleExecutable
- $(EXECUTABLE_NAME)
- CFBundleIconFile
-
- CFBundleIdentifier
- $(PRODUCT_BUNDLE_IDENTIFIER)
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleName
- $(PRODUCT_NAME)
- CFBundlePackageType
- APPL
- CFBundleShortVersionString
- $(FLUTTER_BUILD_NAME)
- CFBundleVersion
- $(FLUTTER_BUILD_NUMBER)
- LSMinimumSystemVersion
- $(MACOSX_DEPLOYMENT_TARGET)
- NSHumanReadableCopyright
- $(PRODUCT_COPYRIGHT)
- NSMainNibFile
- MainMenu
- NSPrincipalClass
- NSApplication
-
-
+
+ CFBundleDevelopmentRegion
+ $(DEVELOPMENT_LANGUAGE)
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIconFile
+
+ CFBundleIdentifier
+ $(PRODUCT_BUNDLE_IDENTIFIER)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ $(PRODUCT_NAME)
+ CFBundlePackageType
+ APPL
+ CFBundleShortVersionString
+ $(FLUTTER_BUILD_NAME)
+ CFBundleVersion
+ $(FLUTTER_BUILD_NUMBER)
+ LSMinimumSystemVersion
+ $(MACOSX_DEPLOYMENT_TARGET)
+ NSHumanReadableCopyright
+ $(PRODUCT_COPYRIGHT)
+ NSMainNibFile
+ MainMenu
+ NSPrincipalClass
+ NSApplication
+ CFBundleLocalizations
+
+ en
+ es
+
+
+
\ No newline at end of file
diff --git a/pubspec.lock b/pubspec.lock
index 13f438c..272bd03 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -193,6 +193,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "3.0.3"
+ csv:
+ dependency: transitive
+ description:
+ name: csv
+ sha256: "63ed2871dd6471193dffc52c0e6c76fb86269c00244d244297abbb355c84a86e"
+ url: "https://pub.dev"
+ source: hosted
+ version: "5.1.1"
cupertino_icons:
dependency: "direct main"
description:
@@ -294,6 +302,11 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.0.3"
+ flutter_localizations:
+ dependency: "direct main"
+ description: flutter
+ source: sdk
+ version: "0.0.0"
flutter_riverpod:
dependency: "direct main"
description:
@@ -376,6 +389,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "4.0.2"
+ intl:
+ dependency: transitive
+ description:
+ name: intl
+ sha256: "3bc132a9dbce73a7e4a21a17d06e1878839ffbf975568bc875c60537824b0c4d"
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.18.1"
io:
dependency: transitive
description:
@@ -392,6 +413,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.7.1"
+ json2yaml:
+ dependency: transitive
+ description:
+ name: json2yaml
+ sha256: da94630fbc56079426fdd167ae58373286f603371075b69bf46d848d63ba3e51
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.0.1"
json_annotation:
dependency: transitive
description:
@@ -661,6 +690,30 @@ packages:
description: flutter
source: sdk
version: "0.0.99"
+ slang:
+ dependency: "direct main"
+ description:
+ name: slang
+ sha256: "95dee03eb3fd1b36c99f365d4eace270a0d83c6148f8e7d1057806ef60cfaf12"
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.29.0"
+ slang_build_runner:
+ dependency: "direct dev"
+ description:
+ name: slang_build_runner
+ sha256: "929ea4bf24f11e09afd2b01abd658f550da7eb4039ae83d91bc220f942e18cb3"
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.29.0"
+ slang_flutter:
+ dependency: "direct main"
+ description:
+ name: slang_flutter
+ sha256: "34c7cf297c608e24d3957a29e75c6790f4dbbfb1a4783d261a6c1e33ede7ad0f"
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.29.0"
source_gen:
dependency: transitive
description:
diff --git a/pubspec.yaml b/pubspec.yaml
index dc67395..545d0cc 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -30,6 +30,8 @@ environment:
dependencies:
flutter:
sdk: flutter
+ flutter_localizations:
+ sdk: flutter
cupertino_icons: ^1.0.2
flutter_riverpod: ^2.4.10
go_router: ^13.2.0
@@ -41,6 +43,8 @@ dependencies:
segmented_button_slide: ^1.0.4
dio: ^5.4.1
uuid: ^4.3.3
+ slang: ^3.29.0
+ slang_flutter: ^3.29.0
dev_dependencies:
build_runner: ^2.4.8
@@ -50,6 +54,7 @@ dev_dependencies:
sdk: flutter
riverpod_generator: ^2.3.11
riverpod_lint: ^2.3.9
+ slang_build_runner: ^3.29.0
# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec