【问题标题】:Is it possible to replace {} with a backspace for localizations是否可以用退格替换 {} 以进行本地化
【发布时间】:2021-10-14 14:48:46
【问题描述】:

我们正在使用flutter easy localizations,并且我们有使用参数的文本。例如,我们的localizations 文档中有一个字符串,如下所示,

{
  "someAppText":"This is {} app text {}."
}

但有时参数会是空的。这将导致以下文本

This is[SPACE][SPACE]app text[SPACE].

空间仍然存在的地方。没有参数时是否可以退格?

【问题讨论】:

  • 我的回答能解决你的问题吗?

标签: json flutter dart localization


【解决方案1】:

首先,如何使用plural?听起来您想为不同类型的数据使用不同的文本。当 arg 为空时,我没有提出其他示例,所以如果不是您的情况,您能否举一个具体的例子?

其次,您可以按如下方式进行简单的字符串操作(伪代码)。代码只演示了最简单的情况(为了简明扼要),但是扩展到完整的情况是微不足道的。

String myTranslate(String formatString, List<String> args) {
  const EMPTY_MARKER = 'EMPTY_MARKER';
  final transformedArgs = args.map((arg) => arg.isEmpty ? EMPTY_MARKER : arg).toList();
  final rawString = formatString.tr(transformedArgs);
  return rawString.replaceAll(' $EMPTY_MARKER', '');
}

然后在您的示例中,它将输出:This is[SPACE]app text.

【讨论】:

    【解决方案2】:

    我们不能在 JSON 文件中添加任何方法,只需要使用它的简单 map 数据

    所以

    一种变通解决方案将在 JSON 中使用特殊字符串,以便能够在运行时检测和处理它们

    假设 JSON 会有这个

    {
      "someAppText": "This is #VAR01 app text #VAR02."
    }
    

    然后让我们创建另一个具有处理这些特殊单词的方法的类,它们应该检测它们,并用其他动态输入替换它们

    所以

        class JSONWorkAround {
    
      /// A - need to define the string pattern we are using in the string which I assumed to look like '#VAR00'
      /// let's call them jsonVariables
      /// NOTE : if you would like to name them #VAR000 ,, then regExp would be r'#VAR...'
      static RegExp regExp = RegExp(r'#VAR..');
    
      /// B - let's make a tracker for any word that matches this regExp in any input string
      static List<String> _searchJSONVariablesByRegExp({@required String text, @required RegExp regExp}){
    
        List<String> _strings;
    
        /// always check if not null before we do stuff to avoid errors and save performance
        if (text != null){
          _strings = regExp.allMatches(text).map((m) => m.group(0)).toList();
    
    
    
        }
    
        return _strings;
      }
    
      /// C - let's make the tracker specifically for those JSONVariables from a string received from the JSON doc "let's call it rawString"
      static List<String> _searchJSONVariablesFromRawString({@required String rawString}){
        final List<String> _jsonVariables = _searchJSONVariablesByRegExp(text: rawString, regExp: regExp);
        return _jsonVariables;
      }
    
      /// E - let's see what to do with the search result
      static List<SpecialWord> _processJSONVariables(List<String> jsonVariables){
    
        List<SpecialWord> _outputSpecialWords = <SpecialWord>[];
    
        /// so w notice we will need to process each one alone,, so we loop them out
        if(jsonVariables != null && jsonVariables.isNotEmpty){
    
          jsonVariables.forEach((jsonVariable) {
    
            /// we should receive a substitute string instead of that #VAR00 special string,, so ..
            /// actually we need to receive a string that is accompanied with its cipher special thing to be able to go back to the sentence and change it,,, like using this special #VAR00 thing as ID
            /// and I don't like map<String, dynamic> but I would rather create a model class ,, will be written down there at the end of this class
            final SpecialWord _substitute = _processSingleJSONVariable(jsonVariable: jsonVariable);
    
            /// then we add them to the output List
            if (_substitute != null){
              _outputSpecialWords.add(_substitute);
            }
          });
    
    
        }
    
        return _outputSpecialWords;
      }
    
      /// D - need to receive both the substitute and its (JSONSpecialVariable / ID) to be able to search for it and process it in the original string
      static SpecialWord _processSingleJSONVariable({@required String jsonVariable}){
    
        final SpecialWord _substitute = SpecialWord.getSpecialWordFromAllSpecialWordsByID(jsonVariable);
    
        return _substitute;
      }
    
      /// F - finally after receiving the substitutes inside a list<SpecialWord>,, we get get back the original String with the substitutes
      static String processJSONStringThatContainsThoseSpecialVariables(String rawString){
    
        /// this has to initialize with the initial raw string value to be processed
        String _processedString = rawString;
    
        final List<String> _jsonVariables = _searchJSONVariablesFromRawString(rawString: rawString);
    
        if (_jsonVariables != null && _jsonVariables.isNotEmpty){
    
          final List<SpecialWord> _specialWords = _processJSONVariables(_jsonVariables);
    
          /// then we need to change each jsonVariable with its substitute
          _specialWords.forEach((specialWord) {
    
            _processedString = _replaceSubStringWith(
                subStringToReplace: specialWord.id,
                replacement: specialWord.substitute,
                input: _processedString,
            );
    
          });
        }
    
        return _processedString;
      }
    
      /// G - a text replacing method to easily replace a given subString from a string with another value
      static String _replaceSubStringWith({@required String subStringToReplace, @required String replacement, @required String input}){
        final String _output = input.replaceAll(subStringToReplace, replacement);
        return _output;
      }
    
    }
    
    class SpecialWord{
      final String id;
      final String substitute; // you can change this to be more complex to adapt to many languages or other things
    
      const SpecialWord({
        @required this.id,
        @required this.substitute,
    });
    
      /// lets create a list of constants that u may change in future and call from db or wherever
      static const List<SpecialWord> _allSpecialWords = const <SpecialWord>[
    
        SpecialWord(id: '#VAR01', substitute: 'Baby'),
        SpecialWord(id: '#VAR02', substitute: 'Cool'),
        SpecialWord(id: '#VAR03', substitute: 'You got the Idea'),
    
      ];
    
      /// I like to pamper myself with super quick methods to be clean and organized
      static SpecialWord getSpecialWordFromAllSpecialWordsByID(String id){
        SpecialWord _foundWord;
    
        if (id != null){
    
          _foundWord = _allSpecialWords.firstWhere((word) => word.id == id, orElse: () => null);
    
        }
    
        return _foundWord;
      }
    
    }
    

    然后让我们做一个小方法测试,以确保这个样板在工程代码上的安全性

      test("Testing JSON Variables work around idea", () async {
    
        String _rawString = "This is #VAR01 app text #VAR02.";
    
        String _processedString = JSONWorkAround.processJSONStringThatContainsThoseSpecialVariables(_rawString);
    
        String _expectation = "This is Baby app text Cool.";
    
        expect(_processedString, _expectation);
    
      });
    

    但现在你可能会问自己,是否值得,我是否过度设计了东西,有没有更明智的解决方案?,也许只是从一开始就将每个案例保存在 json 中,我不不知道,

    恐怕我的解决方案过于复杂,但它的作用就像一个魅力

    【讨论】:

      【解决方案3】:

      我不确定我是否理解您的问题。但请尝试以下方法。

      添加两种翻译,一种用于空参数someAppTextEmpty,另一种用于常规someAppText

      {
        "someAppText": "This is {} app text {}.",
        "someAppTextEmpty": "This is the alternative app text."
      }
      

      然后检查参数是否为空以获得正确的翻译键:

      final String translationKey = argument.isNotEmpty
        ? 'someAppText' : 'someAppTextEmpty';
      

      然后像这样将变量translationKey传递给easy_localization的翻译函数:

      final String title = tr(translationKey);
      
      // Or
      
      Text(translationKey).tr();
      
      // Or
      
      translationKey.tr();
      

      【讨论】:

        【解决方案4】:

        没有。

        无论有没有 easy_localization,Dart 中的退格字符在字符串中占用 1 个空格,而不是删除 1 个空格。这是我通过反复试验得出的结论。

        我的建议:

        1. 创建一个名为 BACKSPACE 的字符串,其从未使用过的值以空格开头,例如:

          final String BACKSPACE = 'NEVER_USED_VALUE';
          
        2. 适当时,将 BACKSPACE 分配给 value1 和 value2 而不是空字符串。

        3. 然后,这样做:

          'someAppText'.tr(value1, value2).replaceAll(' ' + BACKSPACE, '');
          

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2012-07-28
          • 2015-08-05
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多