Skip to content

Commit 541afae

Browse files
author
Hans Muller
authored
Localizations for Material (flutter#11832)
1 parent 0323f2d commit 541afae

File tree

16 files changed

+627
-47
lines changed

16 files changed

+627
-47
lines changed

dev/tools/gen_localizations.dart

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
// Copyright 2017 The Chromium Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
// Given a directory that contains localized ".arb" (application resource
6+
// bundle) files, generates a Dart "localizations" Map definition that combines
7+
// the contents of the arb files. The map can be used to lookup a localized
8+
// string: localizations[localeString][resourceId].
9+
//
10+
// See *.arb and localizations.dart in packages/flutter/lib/src/material/i18n/.
11+
//
12+
// The arb (JSON) format files must contain a single map indexed by locale.
13+
// Each map value is itself a map with resource identifier keys and localized
14+
// resource string values.
15+
//
16+
// The arb filenames are assumed to end in "prefix_lc.arb" or "prefix_lc_cc.arb",
17+
// where prefix is the 2nd command line argument, lc is a language code and cc
18+
// is the country code. In most cases both codes are just two characters. A typical
19+
// filename would be "material_en.arb".
20+
//
21+
// This app is typically run by hand when a module's .arb files have been
22+
// updated.
23+
//
24+
// Usage: dart gen_localizations.dart directory prefix
25+
26+
import 'dart:convert' show JSON;
27+
import 'dart:io';
28+
29+
const String outputHeader = '''
30+
// Copyright 2017 The Chromium Authors. All rights reserved.
31+
// Use of this source code is governed by a BSD-style license that can be
32+
// found in the LICENSE file.
33+
34+
// This file has been automatically generated. Please do not edit it manually.
35+
// To regenerate the file, use:
36+
// @(regenerate)
37+
''';
38+
39+
final Map<String, Map<String, String>> localeToResources = <String, Map<String, String>>{};
40+
41+
// Return s as a Dart-parseable raw string in double quotes. Expand double quotes:
42+
// foo => r"foo"
43+
// foo "bar" => r"foo " '"' r"bar" '"'
44+
String generateString(String s) {
45+
if (!s.contains('"'))
46+
return 'r"$s"';
47+
48+
final StringBuffer output = new StringBuffer();
49+
bool started = false; // Have we started writing a raw string.
50+
for (int i = 0; i < s.length; i++) {
51+
if (s[i] == '"') {
52+
if (started)
53+
output.write('"');
54+
output.write(' \'"\' ');
55+
started = false;
56+
} else if (!started) {
57+
output.write('r"${s[i]}');
58+
started = true;
59+
} else {
60+
output.write(s[i]);
61+
}
62+
}
63+
if (started)
64+
output.write('"');
65+
return output.toString();
66+
}
67+
68+
String generateLocalizationsMap() {
69+
final StringBuffer output = new StringBuffer();
70+
71+
output.writeln('const Map<String, Map<String, String>> localizations = const <String, Map<String, String>> {');
72+
73+
final String lastLocale = localeToResources.keys.last;
74+
for (String locale in localeToResources.keys) {
75+
output.writeln(' "$locale": const <String, String>{');
76+
77+
final Map<String, String> resources = localeToResources[locale];
78+
final String lastName = resources.keys.last;
79+
for (String name in resources.keys) {
80+
final String comma = name == lastName ? "" : ",";
81+
final String value = generateString(resources[name]);
82+
output.writeln(' "$name": $value$comma');
83+
}
84+
final String comma = locale == lastLocale ? "" : ",";
85+
output.writeln(' }$comma');
86+
}
87+
88+
output.writeln('};');
89+
return output.toString();
90+
}
91+
92+
void processBundle(File file, String locale) {
93+
localeToResources[locale] ??= <String, String>{};
94+
final Map<String, String> resources = localeToResources[locale];
95+
final Map<String, dynamic> bundle = JSON.decode(file.readAsStringSync());
96+
for (String key in bundle.keys) {
97+
// The ARB file resource "attributes" for foo are called @foo.
98+
if (key.startsWith('@'))
99+
continue;
100+
resources[key] = bundle[key];
101+
}
102+
}
103+
104+
void main(List<String> args) {
105+
if (args.length != 2)
106+
stderr.writeln('Usage: dart gen_localizations.dart directory prefix');
107+
108+
// filenames are assumed to end in "prefix_lc.arb" or "prefix_lc_cc.arb", where prefix
109+
// is the 2nd command line argument, lc is a language code and cc is the country
110+
// code. In most cases both codes are just two characters.
111+
112+
final Directory directory = new Directory(args[0]);
113+
final String prefix = args[1];
114+
final RegExp filenameRE = new RegExp('${prefix}_(\\w+)\\.arb\$');
115+
116+
for (FileSystemEntity entity in directory.listSync()) {
117+
final String path = entity.path;
118+
if (FileSystemEntity.isFileSync(path) && filenameRE.hasMatch(path)) {
119+
final String locale = filenameRE.firstMatch(path)[1];
120+
processBundle(new File(path), locale);
121+
}
122+
}
123+
124+
final String regenerate = 'dart gen_localizations ${directory.path} ${args[1]}';
125+
print(outputHeader.replaceFirst('@(regenerate)', regenerate));
126+
print(generateLocalizationsMap());
127+
}

packages/flutter/lib/src/material/app.dart

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,19 +26,17 @@ const TextStyle _errorTextStyle = const TextStyle(
2626
decorationStyle: TextDecorationStyle.double
2727
);
2828

29-
// Delegate that fetches the default (English) strings.
3029
class _MaterialLocalizationsDelegate extends LocalizationsDelegate<MaterialLocalizations> {
3130
const _MaterialLocalizationsDelegate();
3231

3332
@override
34-
Future<MaterialLocalizations> load(Locale locale) {
35-
return new SynchronousFuture<MaterialLocalizations>(const MaterialLocalizations());
36-
}
33+
Future<MaterialLocalizations> load(Locale locale) => DefaultMaterialLocalizations.load(locale);
3734

3835
@override
3936
bool shouldReload(_MaterialLocalizationsDelegate old) => false;
4037
}
4138

39+
4240
/// An application that uses material design.
4341
///
4442
/// A convenience widget that wraps a number of widgets that are commonly
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
// Copyright 2017 The Chromium Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
// This file has been automatically generated. Please do not edit it manually.
6+
// To regenerate the file, use:
7+
// dart gen_localizations packages/flutter/lib/src/material/i18n material
8+
9+
const Map<String, Map<String, String>> localizations = const <String, Map<String, String>> {
10+
"ar": const <String, String>{
11+
"openAppDrawerTooltip": r"افتح قائمة التنقل",
12+
"backButtonTooltip": r"الى الخلف",
13+
"closeButtonTooltip": r"إغلا",
14+
"nextMonthTooltip": r"الشهر القادم",
15+
"previousMonthTooltip": r"الشهر الماضى"
16+
},
17+
"it": const <String, String>{
18+
"openAppDrawerTooltip": r"Apri il menu di navigazione",
19+
"backButtonTooltip": r"Indietro",
20+
"closeButtonTooltip": r"Chiudi",
21+
"nextMonthTooltip": r"Il prossimo mese",
22+
"previousMonthTooltip": r"Il mese scorso"
23+
},
24+
"pt": const <String, String>{
25+
"openAppDrawerTooltip": r"Abrir menu de navegação",
26+
"backButtonTooltip": r"Costas",
27+
"closeButtonTooltip": r"Fechar",
28+
"nextMonthTooltip": r"Próximo mês",
29+
"previousMonthTooltip": r"Mês anterior"
30+
},
31+
"es": const <String, String>{
32+
"openAppDrawerTooltip": r"Abrir el menú de navegación",
33+
"backButtonTooltip": r"Espalda",
34+
"closeButtonTooltip": r"Cerrar",
35+
"nextMonthTooltip": r"Próximo mes",
36+
"previousMonthTooltip": r"mes anterior"
37+
},
38+
"fr": const <String, String>{
39+
"openAppDrawerTooltip": r"Ouvrir le menu de navigation",
40+
"backButtonTooltip": r"Arrière",
41+
"closeButtonTooltip": r"Fermer",
42+
"nextMonthTooltip": r"Mois Suivant",
43+
"previousMonthTooltip": r"Le mois précédent"
44+
},
45+
"zh": const <String, String>{
46+
"openAppDrawerTooltip": r"打开导航菜单",
47+
"backButtonTooltip": r"背部",
48+
"closeButtonTooltip": r"关",
49+
"nextMonthTooltip": r"-下月就29了。",
50+
"previousMonthTooltip": r"前一个月"
51+
},
52+
"en": const <String, String>{
53+
"openAppDrawerTooltip": r"Open navigation menu",
54+
"backButtonTooltip": r"Back",
55+
"closeButtonTooltip": r"Close",
56+
"nextMonthTooltip": r"Next month",
57+
"previousMonthTooltip": r"Previous month"
58+
},
59+
"de": const <String, String>{
60+
"openAppDrawerTooltip": r"Navigationsmenü öffnen",
61+
"backButtonTooltip": r"Zurück",
62+
"closeButtonTooltip": r"Schließen ",
63+
"nextMonthTooltip": r"Nächster Monat",
64+
"previousMonthTooltip": r"Letzter Monat"
65+
},
66+
"ja": const <String, String>{
67+
"openAppDrawerTooltip": r"ナビゲーションメニューを開く",
68+
"backButtonTooltip": r"バック",
69+
"closeButtonTooltip": r"閉じる",
70+
"nextMonthTooltip": r"来月",
71+
"previousMonthTooltip": r"前の月"
72+
},
73+
"ru": const <String, String>{
74+
"openAppDrawerTooltip": r"Открыть меню навигации",
75+
"backButtonTooltip": r"назад",
76+
"closeButtonTooltip": r"Закрыть",
77+
"nextMonthTooltip": r"В следующем месяце",
78+
"previousMonthTooltip": r"Предыдущий месяц"
79+
}
80+
};
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
{
2+
"openAppDrawerTooltip": "افتح قائمة التنقل",
3+
"@openAppDrawerTooltip": {
4+
"description": "The tooltip for the leading AppBar menu (aka 'hamburger') button",
5+
"type": "text"
6+
},
7+
"backButtonTooltip": "الى الخلف",
8+
"@backButtonTooltip": {
9+
"description": "The BackButton's tooltip",
10+
"type": "text"
11+
},
12+
"closeButtonTooltip": "إغلا",
13+
"@closeButtonTooltip": {
14+
"description": "The CloseButton's tooltip",
15+
"type": "text"
16+
},
17+
"nextMonthTooltip": "الشهر القادم",
18+
"@nextMonthTooltip": {
19+
"description": "The tooltip for the MonthPicker's 'next month' button.",
20+
"type": "text"
21+
},
22+
"previousMonthTooltip": "الشهر الماضى",
23+
"@previousMonthTooltip": {
24+
"description": "The tooltip for the MonthPicker's 'previous month' button.",
25+
"type": "text"
26+
}
27+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
{
2+
"openAppDrawerTooltip": "Navigationsmenü öffnen",
3+
"@openAppDrawerTooltip": {
4+
"description": "The tooltip for the leading AppBar menu (aka 'hamburger') button",
5+
"type": "text"
6+
},
7+
"backButtonTooltip": "Zurück",
8+
"@backButtonTooltip": {
9+
"description": "The BackButton's tooltip",
10+
"type": "text"
11+
},
12+
"closeButtonTooltip": "Schließen ",
13+
"@closeButtonTooltip": {
14+
"description": "The CloseButton's tooltip",
15+
"type": "text"
16+
},
17+
"nextMonthTooltip": "Nächster Monat",
18+
"@nextMonthTooltip": {
19+
"description": "The tooltip for the MonthPicker's 'next month' button.",
20+
"type": "text"
21+
},
22+
"previousMonthTooltip": "Letzter Monat",
23+
"@previousMonthTooltip": {
24+
"description": "The tooltip for the MonthPicker's 'previous month' button.",
25+
"type": "text"
26+
}
27+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
{
2+
"openAppDrawerTooltip": "Open navigation menu",
3+
"@openAppDrawerTooltip": {
4+
"description": "The tooltip for the leading AppBar menu (aka 'hamburger') button",
5+
"type": "text"
6+
},
7+
8+
"backButtonTooltip": "Back",
9+
"@backButtonTooltip": {
10+
"description": "The BackButton's tooltip",
11+
"type": "text"
12+
},
13+
14+
"closeButtonTooltip": "Close",
15+
"@closeButtonTooltip": {
16+
"description": "The CloseButton's tooltip",
17+
"type": "text"
18+
},
19+
20+
"nextMonthTooltip": "Next month",
21+
"@nextMonthTooltip": {
22+
"description": "The tooltip for the MonthPicker's 'next month' button.",
23+
"type": "text"
24+
},
25+
26+
"previousMonthTooltip": "Previous month",
27+
"@previousMonthTooltip": {
28+
"description": "The tooltip for the MonthPicker's 'previous month' button.",
29+
"type": "text"
30+
}
31+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
{
2+
"openAppDrawerTooltip": "Abrir el menú de navegación",
3+
"@openAppDrawerTooltip": {
4+
"description": "The tooltip for the leading AppBar menu (aka 'hamburger') button",
5+
"type": "text"
6+
},
7+
"backButtonTooltip": "Espalda",
8+
"@backButtonTooltip": {
9+
"description": "The BackButton's tooltip",
10+
"type": "text"
11+
},
12+
"closeButtonTooltip": "Cerrar",
13+
"@closeButtonTooltip": {
14+
"description": "The CloseButton's tooltip",
15+
"type": "text"
16+
},
17+
"nextMonthTooltip": "Próximo mes",
18+
"@nextMonthTooltip": {
19+
"description": "The tooltip for the MonthPicker's 'next month' button.",
20+
"type": "text"
21+
},
22+
"previousMonthTooltip": "mes anterior",
23+
"@previousMonthTooltip": {
24+
"description": "The tooltip for the MonthPicker's 'previous month' button.",
25+
"type": "text"
26+
}
27+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
{
2+
"openAppDrawerTooltip": "Ouvrir le menu de navigation",
3+
"@openAppDrawerTooltip": {
4+
"description": "The tooltip for the leading AppBar menu (aka 'hamburger') button",
5+
"type": "text"
6+
},
7+
"backButtonTooltip": "Arrière",
8+
"@backButtonTooltip": {
9+
"description": "The BackButton's tooltip",
10+
"type": "text"
11+
},
12+
"closeButtonTooltip": "Fermer",
13+
"@closeButtonTooltip": {
14+
"description": "The CloseButton's tooltip",
15+
"type": "text"
16+
},
17+
"nextMonthTooltip": "Mois Suivant",
18+
"@nextMonthTooltip": {
19+
"description": "The tooltip for the MonthPicker's 'next month' button.",
20+
"type": "text"
21+
},
22+
"previousMonthTooltip": "Le mois précédent",
23+
"@previousMonthTooltip": {
24+
"description": "The tooltip for the MonthPicker's 'previous month' button.",
25+
"type": "text"
26+
}
27+
}

0 commit comments

Comments
 (0)