【问题标题】:Getting localized strings in the headless mode在无头模式下获取本地化字符串
【发布时间】:2020-06-07 08:11:05
【问题描述】:

我目前正在尝试在无头模式下运行应用程序,我做了什么我定义了后台回调:

void callbackInBackground() {
 // Invoked from the service
}

我正在尝试从回调中获取具有当前语言环境的本地化字符串。

由于我需要 BuildContext 来执行此操作,所以我不知道如何检索它们。

有什么提示和技巧吗?

【问题讨论】:

标签: android flutter headless


【解决方案1】:

您可以使用easy_localization 插件来实现这一点。此外,您可以使用flutter_background_fetch 插件进行无头执行。

easy_localization 示例:

import 'dart:developer';
import 'dart:ui';

import 'lang_view.dart';
import 'package:flutter/material.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:easy_localization_loader/easy_localization_loader.dart';
import 'package:flutter_icons/flutter_icons.dart';

import 'generated/locale_keys.g.dart';

void main() {
  runApp(EasyLocalization(
    child: MyApp(),
    supportedLocales: [
      Locale('en', 'US'),
      Locale('ar', 'DZ'),
      Locale('de', 'DE'),
      Locale('ru', 'RU')
    ],
    path: 'resources/langs/langs.csv', //'resources/langs',
    // fallbackLocale: Locale('en', 'US'),
    // startLocale: Locale('de', 'DE'),
    // saveLocale: false,
    // useOnlyLangCode: true,
    // preloaderColor: Colors.black,
    // preloaderWidget: CustomPreloaderWidget(),

    // optional assetLoader default used is RootBundleAssetLoader which uses flutter's assetloader
    // install easy_localization_loader for enable custom loaders
    // assetLoader: RootBundleAssetLoader()
    // assetLoader: HttpAssetLoader()
    // assetLoader: FileAssetLoader()
    assetLoader: CsvAssetLoader()
    // assetLoader: YamlAssetLoader() //multiple files
    // assetLoader: YamlSingleAssetLoader() //single file
    // assetLoader: XmlAssetLoader() //multiple files
    // assetLoader: XmlSingleAssetLoader() //single file
    // assetLoader: CodegenLoader()
  ));
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    log(context.locale.toString(),
        name: '${this} # locale Context');
    log('title'.tr().toString(), name: '${this} # locale');
    return MaterialApp(
      title: 'title'.tr(),
      localizationsDelegates: context.localizationDelegates,
      supportedLocales: context.supportedLocales,
      locale: context.locale,
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Easy localization'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int counter = 0;
  bool _gender = true;

  void incrementCounter() {
    setState(() {
      counter++;
    });
  }

  void switchGender(bool val) {
    setState(() {
      _gender = val;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(LocaleKeys.title).tr(context: context),
        //Text(AppLocalizations.of(context).tr('title')),
        actions: <Widget>[
          FlatButton(
            child: Icon(Icons.language),
            onPressed: () {
              Navigator.push(
                context,
                MaterialPageRoute(
                    builder: (_) => LanguageView(), fullscreenDialog: true),
              );
            },
          ),
        ],
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Spacer(
              flex: 1,
            ),
            Text(
              LocaleKeys.gender_with_arg,
              style: TextStyle(
                  color: Colors.grey.shade600,
                  fontSize: 19,
                  fontWeight: FontWeight.bold),
            ).tr(args: ['aissat'], gender: _gender ? 'female' : 'male'),
            Text(
              tr(LocaleKeys.gender, gender: _gender ? 'female' : 'male'),
              style: TextStyle(
                  color: Colors.grey.shade600,
                  fontSize: 15,
                  fontWeight: FontWeight.bold),
            ),
            Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Icon(FontAwesome.male),
                Switch(value: _gender, onChanged: switchGender),
                Icon(FontAwesome.female),
              ],
            ),
            Spacer(
              flex: 1,
            ),
            Text(LocaleKeys.msg).tr(args: ['aissat', 'Flutter']),
            Text(LocaleKeys.msg_named).tr(namedArgs: {'lang': 'Dart'}, args: ['Easy localization']),
            Text(LocaleKeys.clicked).plural(counter),
            FlatButton(
              onPressed: () {
                incrementCounter();
              },
              child: Text(LocaleKeys.clickMe).tr(),
            ),
            SizedBox(
              height: 15,
            ),
            Text(
                plural(LocaleKeys.amount, counter,
                    format: NumberFormat.currency(
                        locale: Intl.defaultLocale, symbol: '€')),
                style: TextStyle(
                    color: Colors.grey.shade900,
                    fontSize: 18,
                    fontWeight: FontWeight.bold)),
            SizedBox(
              height: 20,
            ),
            RaisedButton(
              onPressed: () {
                context.deleteSaveLocale();
              },
              child: Text(LocaleKeys.reset_locale).tr(),
            ),
            Spacer(
              flex: 1,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: incrementCounter,
        child: Text('+1'),
      ),
    );
  }
}

class CustomPreloaderWidget extends StatelessWidget {
  const CustomPreloaderWidget({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    log('Loading custom preloder widget');
    return Container(
      child: Center(
        child: CircularProgressIndicator()
      ),
    );
  }
}

【讨论】:

    【解决方案2】:

    有一个本地化库flutter_localizations你可以使用它。

    我还分享了代码,您可以直接使用它并根据您的要求进行修改。 您需要添加到 lang 文件夹中的 json 文件中,所有字符串都在这些 json 文件中。

    import 'package:flutter/material.dart';
    import 'package:flutter_localizations/flutter_localizations.dart';
    
    import 'app_localizations.dart';
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          // List all of the app's supported locales here
          supportedLocales: [
            Locale('en', 'US'),
            Locale('sk', 'SK'),
          ],
          // These delegates make sure that the localization data for the proper language is loaded
          localizationsDelegates: [
            // A class which loads the translations from JSON files
            AppLocalizations.delegate,
            // Built-in localization of basic text for Material widgets
            GlobalMaterialLocalizations.delegate,
            // Built-in localization for text direction LTR/RTL
            GlobalWidgetsLocalizations.delegate,
          ],
          // Returns a locale which will be used by the app
          localeResolutionCallback: (locale, supportedLocales) {
            // Check if the current device locale is supported
            for (var supportedLocale in supportedLocales) {
              if (supportedLocale.languageCode == locale.languageCode &&
                  supportedLocale.countryCode == locale.countryCode) {
                return supportedLocale;
              }
            }
            // If the locale of the device is not supported, use the first one
            // from the list (English, in this case).
            return supportedLocales.first;
          },
          home: MyHomePage(),
        );
      }
    }
    
    class MyHomePage extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: Center(
            child: Padding(
              padding: const EdgeInsets.all(8.0),
              child: Column(
                mainAxisSize: MainAxisSize.min,
                children: <Widget>[
                  Text(
                    AppLocalizations.of(context).translate('first_string'),
                    style: TextStyle(fontSize: 25),
                    textAlign: TextAlign.center,
                  ),
                  SizedBox(height: 10),
                  Text(
                    AppLocalizations.of(context).translate('second_string'),
                    style: TextStyle(fontSize: 25),
                    textAlign: TextAlign.center,
                  ),
                  SizedBox(height: 10),
                  Text(
                    'This will not be translated.',
                    style: TextStyle(fontSize: 25),
                    textAlign: TextAlign.center,
                  ),
                ],
              ),
            ),
          ),
        );
      }
    }
    

    app_localizations.dart

    import 'dart:async';
    import 'dart:convert';
    
    import 'package:flutter/material.dart';
    import 'package:flutter/services.dart';
    
    class AppLocalizations {
      final Locale locale;
    
      AppLocalizations(this.locale);
    
      // Helper method to keep the code in the widgets concise
      // Localizations are accessed using an InheritedWidget "of" syntax
      static AppLocalizations of(BuildContext context) {
        return Localizations.of<AppLocalizations>(context, AppLocalizations);
      }
    
      // Static member to have a simple access to the delegate from the MaterialApp
      static const LocalizationsDelegate<AppLocalizations> delegate =
          _AppLocalizationsDelegate();
    
      Map<String, String> _localizedStrings;
    
      Future<bool> load() async {
        // Load the language JSON file from the "lang" folder
        String jsonString =
            await rootBundle.loadString('lang/${locale.languageCode}.json');
        Map<String, dynamic> jsonMap = json.decode(jsonString);
    
        _localizedStrings = jsonMap.map((key, value) {
          return MapEntry(key, value.toString());
        });
    
        return true;
      }
    
      // This method will be called from every widget which needs a localized text
      String translate(String key) {
        return _localizedStrings[key];
      }
    }
    
    // LocalizationsDelegate is a factory for a set of localized resources
    // In this case, the localized strings will be gotten in an AppLocalizations object
    class _AppLocalizationsDelegate
        extends LocalizationsDelegate<AppLocalizations> {
      // This delegate instance will never change (it doesn't even have fields!)
      // It can provide a constant constructor.
      const _AppLocalizationsDelegate();
    
      @override
      bool isSupported(Locale locale) {
        // Include all of your supported language codes here
        return ['en', 'sk'].contains(locale.languageCode);
      }
    
      @override
      Future<AppLocalizations> load(Locale locale) async {
        // AppLocalizations class is where the JSON loading actually runs
        AppLocalizations localizations = new AppLocalizations(locale);
        await localizations.load();
        return localizations;
      }
    
      @override
      bool shouldReload(_AppLocalizationsDelegate old) => false;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-06-28
      • 1970-01-01
      • 2012-08-20
      • 2019-03-20
      • 1970-01-01
      • 2014-03-11
      • 2013-03-17
      相关资源
      最近更新 更多