i18n Code Style
В данной статье описаны как надо и как не надо менять файлы .i18n.json
Формат ключей
Ключи называем в snake_case
TIP
При генерации кода, генерируются геттеры в snake_case и потом невозможно найти источник локализации поиском по геттеру, потому что в json ключи хранятся в другом формате
json
// [!code class:bad]
"profileWidget": {
"sammaVodkaStart": "To start, begin",
"sammaVodkaPrefix": "Sammagonka — ",
"sammaVodkaContinuePostfix": "'.\nKeep going!",
}
json
// [!code class:good]
"profile_widget": {
"samma_vodka_start": "To start, begin",
"samma_vodka_prefix": "Sammagonka — ",
"samma_vodka_continue_postfix": "'.\nKeep going!",
}
**_text в ключах
Старайся избегать _text в ключах. Ты и так используешь инструмент для текстов, это понятно из контекста
json
// [!code class:bad]
"profile_widget": {
"samma_vodka_start_text": "To start, begin"
}
json
// [!code class:good]
"profile_widget": {
"samma_vodka_start": "To start, begin"
}
Можно использовать одинарный ключ "text", если ничего больше не подходит по смыслу
json
// [!code class:good]
"profile_widget": {
"text": {
"no_progress": "...",
"has_progress": "..."
}
}
Составной текст
Старайся использовать только один ключ в коде для одного кейса вместо составных текстов
json
// [!code class:bad]
"profile": {
"samma_vodka_start": "Для начала — начни",
"samma_vodka_prefix": "Саммагонка — $duration",
"samma_vodka_continue_postfix": "'.\nKeep going!",
}
dart
// [!code class:bad]
final isActive = progress != 0 && progress != 1;
final duration = durationRaw.let((it) => DateTimeUtils.formatDuration(context, it));
final result = durationRaw == null || durationRaw == 0
? context.t.knowledge_sprint.profile_widget.samma_vodka_start_text
: context.t.knowledge_sprint.profile_widget.samma_vodka_prefix +
duration +
(isActive ? context.t.knowledge_sprint.profile_widget.samma_vodka_continue_postfix : '');
return Text(result)
json
// [!code class:good]
"profile": {
"text": {
"no_progress": "Для начала — начни",
"has_progress": "Саммагонка — $duration",
"active": "@:knowledge_sprint.profile.text.has_progress.\nПродолжай!"
}
}
dart
// [!code class:good]
final isActive = progress != 0 && progress != 1;
final duration = durationRaw.let((it) => DateTimeUtils.formatDuration(context, it));
final String text;
if (durationRaw == null || durationRaw == 0) {
text = context.t.knowledge_sprint.profile_widget.text.no_progress;
} else if (isActive) {
text = context.t.knowledge_sprint.profile_widget.text.active(duration: duration!);
} else {
text = context.t.knowledge_sprint.profile_widget.text.has_progress(duration: duration!);
}
return Text(text);
Понятный нейминг
Используй понятный и легкочитаемый нейминг. Старайся избегать двойного отрицания
json
// [!code class:bad]
"bottom_sheet": {
"empty_result": {
"title": "Опа, $name не в саммагонке!"
},
"not_empty_result": {
"title": "$name бьет рекорды:\n $days подряд!"
}
}
json
// [!code class:good]
"bottom_sheet": {
"no_results": {
"title": "Опа, $name не в саммагонке!"
},
"has_results": {
"title": "$name бьет рекорды:\n $days подряд!"
}
}