是否可以将 {} 替换为本地化的退格键
Is it possible to replace {} with a backspace for localizations
我们正在使用 flutter easy localizations
并且我们有使用参数的文本。例如,我们的 localizations
文档中有一个字符串,如下所示,
{
"someAppText":"This is {} app text {}."
}
但有时参数会为空。这将导致以下文本
This is[SPACE][SPACE]app text[SPACE].
空格还在的地方。是否可以在没有参数的情况下退格?
首先,使用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.
我们不能在 JSON 文件中添加任何方法,只能使用它的简单 map data
所以
解决方案将在 JSON 中使用特殊字符串,以便能够在 运行 时间内检测和处理它们
假设 JSON 会有这个
{
"someAppText": "This is #VAR01 app text #VAR02."
}
然后让我们创建另一个class,它有处理这些特殊词的方法,他们应该检测它们,并用其他动态输入替换它们
所以
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从一开始,我不知道,
恐怕我的解决方案过于复杂了,但它的效果很好
我不确定我是否理解您的问题。但请尝试以下操作。
添加两个翻译,一个用于空参数 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();
没有
有或没有 easy_localization,Dart 中的后退 space 字符在字符串中取 1 space 而不是删除 1 space。这是我通过反复试验得出的结论。
我的建议:
创建一个名为 BACKSPACE 的字符串,其中包含一个从未使用过的值,以 space 开头,例如:
final String BACKSPACE = 'NEVER_USED_VALUE';
适当时,将 BACKSPACE 分配给 value1 和 value2 而不是空字符串。
然后,这样做:
'someAppText'.tr(value1, value2).replaceAll(' ' + BACKSPACE, '');
我们正在使用 flutter easy localizations
并且我们有使用参数的文本。例如,我们的 localizations
文档中有一个字符串,如下所示,
{
"someAppText":"This is {} app text {}."
}
但有时参数会为空。这将导致以下文本
This is[SPACE][SPACE]app text[SPACE].
空格还在的地方。是否可以在没有参数的情况下退格?
首先,使用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.
我们不能在 JSON 文件中添加任何方法,只能使用它的简单 map
所以
解决方案将在 JSON 中使用特殊字符串,以便能够在 运行 时间内检测和处理它们
假设 JSON 会有这个
{
"someAppText": "This is #VAR01 app text #VAR02."
}
然后让我们创建另一个class,它有处理这些特殊词的方法,他们应该检测它们,并用其他动态输入替换它们
所以
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从一开始,我不知道,
恐怕我的解决方案过于复杂了,但它的效果很好
我不确定我是否理解您的问题。但请尝试以下操作。
添加两个翻译,一个用于空参数 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();
没有
有或没有 easy_localization,Dart 中的后退 space 字符在字符串中取 1 space 而不是删除 1 space。这是我通过反复试验得出的结论。
我的建议:
创建一个名为 BACKSPACE 的字符串,其中包含一个从未使用过的值,以 space 开头,例如:
final String BACKSPACE = 'NEVER_USED_VALUE';
适当时,将 BACKSPACE 分配给 value1 和 value2 而不是空字符串。
然后,这样做:
'someAppText'.tr(value1, value2).replaceAll(' ' + BACKSPACE, '');