Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
541afae4
Commit
541afae4
authored
Aug 31, 2017
by
Hans Muller
Committed by
GitHub
Aug 31, 2017
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Localizations for Material (#11832)
parent
0323f2dd
Changes
16
Show whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
627 additions
and
47 deletions
+627
-47
gen_localizations.dart
dev/tools/gen_localizations.dart
+127
-0
app.dart
packages/flutter/lib/src/material/app.dart
+2
-4
localizations.dart
packages/flutter/lib/src/material/i18n/localizations.dart
+80
-0
material_ar.arb
packages/flutter/lib/src/material/i18n/material_ar.arb
+27
-0
material_de.arb
packages/flutter/lib/src/material/i18n/material_de.arb
+27
-0
material_en.arb
packages/flutter/lib/src/material/i18n/material_en.arb
+31
-0
material_es.arb
packages/flutter/lib/src/material/i18n/material_es.arb
+27
-0
material_fr.arb
packages/flutter/lib/src/material/i18n/material_fr.arb
+27
-0
material_it.arb
packages/flutter/lib/src/material/i18n/material_it.arb
+27
-0
material_ja.arb
packages/flutter/lib/src/material/i18n/material_ja.arb
+27
-0
material_pt.arb
packages/flutter/lib/src/material/i18n/material_pt.arb
+27
-0
material_ru.arb
packages/flutter/lib/src/material/i18n/material_ru.arb
+27
-0
material_zh.arb
packages/flutter/lib/src/material/i18n/material_zh.arb
+27
-0
material_localizations.dart
...ages/flutter/lib/src/material/material_localizations.dart
+59
-17
localizations.dart
packages/flutter/lib/src/widgets/localizations.dart
+33
-26
localizations_test.dart
packages/flutter/test/material/localizations_test.dart
+52
-0
No files found.
dev/tools/gen_localizations.dart
0 → 100644
View file @
541afae4
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Given a directory that contains localized ".arb" (application resource
// bundle) files, generates a Dart "localizations" Map definition that combines
// the contents of the arb files. The map can be used to lookup a localized
// string: localizations[localeString][resourceId].
//
// See *.arb and localizations.dart in packages/flutter/lib/src/material/i18n/.
//
// The arb (JSON) format files must contain a single map indexed by locale.
// Each map value is itself a map with resource identifier keys and localized
// resource string values.
//
// The arb filenames are assumed to end in "prefix_lc.arb" or "prefix_lc_cc.arb",
// where prefix is the 2nd command line argument, lc is a language code and cc
// is the country code. In most cases both codes are just two characters. A typical
// filename would be "material_en.arb".
//
// This app is typically run by hand when a module's .arb files have been
// updated.
//
// Usage: dart gen_localizations.dart directory prefix
import
'dart:convert'
show
JSON
;
import
'dart:io'
;
const
String
outputHeader
=
'''
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// This file has been automatically generated. Please do not edit it manually.
// To regenerate the file, use:
// @(regenerate)
'''
;
final
Map
<
String
,
Map
<
String
,
String
>>
localeToResources
=
<
String
,
Map
<
String
,
String
>>{};
// Return s as a Dart-parseable raw string in double quotes. Expand double quotes:
// foo => r"foo"
// foo "bar" => r"foo " '"' r"bar" '"'
String
generateString
(
String
s
)
{
if
(!
s
.
contains
(
'"'
))
return
'r"
$s
"'
;
final
StringBuffer
output
=
new
StringBuffer
();
bool
started
=
false
;
// Have we started writing a raw string.
for
(
int
i
=
0
;
i
<
s
.
length
;
i
++)
{
if
(
s
[
i
]
==
'"'
)
{
if
(
started
)
output
.
write
(
'"'
);
output
.
write
(
'
\'
"
\'
'
);
started
=
false
;
}
else
if
(!
started
)
{
output
.
write
(
'r"
${s[i]}
'
);
started
=
true
;
}
else
{
output
.
write
(
s
[
i
]);
}
}
if
(
started
)
output
.
write
(
'"'
);
return
output
.
toString
();
}
String
generateLocalizationsMap
(
)
{
final
StringBuffer
output
=
new
StringBuffer
();
output
.
writeln
(
'const Map<String, Map<String, String>> localizations = const <String, Map<String, String>> {'
);
final
String
lastLocale
=
localeToResources
.
keys
.
last
;
for
(
String
locale
in
localeToResources
.
keys
)
{
output
.
writeln
(
' "
$locale
": const <String, String>{'
);
final
Map
<
String
,
String
>
resources
=
localeToResources
[
locale
];
final
String
lastName
=
resources
.
keys
.
last
;
for
(
String
name
in
resources
.
keys
)
{
final
String
comma
=
name
==
lastName
?
""
:
","
;
final
String
value
=
generateString
(
resources
[
name
]);
output
.
writeln
(
' "
$name
":
$value$comma
'
);
}
final
String
comma
=
locale
==
lastLocale
?
""
:
","
;
output
.
writeln
(
' }
$comma
'
);
}
output
.
writeln
(
'};'
);
return
output
.
toString
();
}
void
processBundle
(
File
file
,
String
locale
)
{
localeToResources
[
locale
]
??=
<
String
,
String
>{};
final
Map
<
String
,
String
>
resources
=
localeToResources
[
locale
];
final
Map
<
String
,
dynamic
>
bundle
=
JSON
.
decode
(
file
.
readAsStringSync
());
for
(
String
key
in
bundle
.
keys
)
{
// The ARB file resource "attributes" for foo are called @foo.
if
(
key
.
startsWith
(
'@'
))
continue
;
resources
[
key
]
=
bundle
[
key
];
}
}
void
main
(
List
<
String
>
args
)
{
if
(
args
.
length
!=
2
)
stderr
.
writeln
(
'Usage: dart gen_localizations.dart directory prefix'
);
// filenames are assumed to end in "prefix_lc.arb" or "prefix_lc_cc.arb", where prefix
// is the 2nd command line argument, lc is a language code and cc is the country
// code. In most cases both codes are just two characters.
final
Directory
directory
=
new
Directory
(
args
[
0
]);
final
String
prefix
=
args
[
1
];
final
RegExp
filenameRE
=
new
RegExp
(
'
${prefix}
_(
\\
w+)
\\
.arb
\$
'
);
for
(
FileSystemEntity
entity
in
directory
.
listSync
())
{
final
String
path
=
entity
.
path
;
if
(
FileSystemEntity
.
isFileSync
(
path
)
&&
filenameRE
.
hasMatch
(
path
))
{
final
String
locale
=
filenameRE
.
firstMatch
(
path
)[
1
];
processBundle
(
new
File
(
path
),
locale
);
}
}
final
String
regenerate
=
'dart gen_localizations
${directory.path}
${args[1]}
'
;
print
(
outputHeader
.
replaceFirst
(
'@(regenerate)'
,
regenerate
));
print
(
generateLocalizationsMap
());
}
packages/flutter/lib/src/material/app.dart
View file @
541afae4
...
...
@@ -26,19 +26,17 @@ const TextStyle _errorTextStyle = const TextStyle(
decorationStyle:
TextDecorationStyle
.
double
);
// Delegate that fetches the default (English) strings.
class
_MaterialLocalizationsDelegate
extends
LocalizationsDelegate
<
MaterialLocalizations
>
{
const
_MaterialLocalizationsDelegate
();
@override
Future
<
MaterialLocalizations
>
load
(
Locale
locale
)
{
return
new
SynchronousFuture
<
MaterialLocalizations
>(
const
MaterialLocalizations
());
}
Future
<
MaterialLocalizations
>
load
(
Locale
locale
)
=>
DefaultMaterialLocalizations
.
load
(
locale
);
@override
bool
shouldReload
(
_MaterialLocalizationsDelegate
old
)
=>
false
;
}
/// An application that uses material design.
///
/// A convenience widget that wraps a number of widgets that are commonly
...
...
packages/flutter/lib/src/material/i18n/localizations.dart
0 → 100644
View file @
541afae4
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// This file has been automatically generated. Please do not edit it manually.
// To regenerate the file, use:
// dart gen_localizations packages/flutter/lib/src/material/i18n material
const
Map
<
String
,
Map
<
String
,
String
>>
localizations
=
const
<
String
,
Map
<
String
,
String
>>
{
"ar"
:
const
<
String
,
String
>{
"openAppDrawerTooltip"
:
r"افتح قائمة التنقل"
,
"backButtonTooltip"
:
r"الى الخلف"
,
"closeButtonTooltip"
:
r"إغلا"
,
"nextMonthTooltip"
:
r"الشهر القادم"
,
"previousMonthTooltip"
:
r"الشهر الماضى"
},
"it"
:
const
<
String
,
String
>{
"openAppDrawerTooltip"
:
r"Apri il menu di navigazione"
,
"backButtonTooltip"
:
r"Indietro"
,
"closeButtonTooltip"
:
r"Chiudi"
,
"nextMonthTooltip"
:
r"Il prossimo mese"
,
"previousMonthTooltip"
:
r"Il mese scorso"
},
"pt"
:
const
<
String
,
String
>{
"openAppDrawerTooltip"
:
r"Abrir menu de navegação"
,
"backButtonTooltip"
:
r"Costas"
,
"closeButtonTooltip"
:
r"Fechar"
,
"nextMonthTooltip"
:
r"Próximo mês"
,
"previousMonthTooltip"
:
r"Mês anterior"
},
"es"
:
const
<
String
,
String
>{
"openAppDrawerTooltip"
:
r"Abrir el menú de navegación"
,
"backButtonTooltip"
:
r"Espalda"
,
"closeButtonTooltip"
:
r"Cerrar"
,
"nextMonthTooltip"
:
r"Próximo mes"
,
"previousMonthTooltip"
:
r"mes anterior"
},
"fr"
:
const
<
String
,
String
>{
"openAppDrawerTooltip"
:
r"Ouvrir le menu de navigation"
,
"backButtonTooltip"
:
r"Arrière"
,
"closeButtonTooltip"
:
r"Fermer"
,
"nextMonthTooltip"
:
r"Mois Suivant"
,
"previousMonthTooltip"
:
r"Le mois précédent"
},
"zh"
:
const
<
String
,
String
>{
"openAppDrawerTooltip"
:
r"打开导航菜单"
,
"backButtonTooltip"
:
r"背部"
,
"closeButtonTooltip"
:
r"关"
,
"nextMonthTooltip"
:
r"-下月就29了。"
,
"previousMonthTooltip"
:
r"前一个月"
},
"en"
:
const
<
String
,
String
>{
"openAppDrawerTooltip"
:
r"Open navigation menu"
,
"backButtonTooltip"
:
r"Back"
,
"closeButtonTooltip"
:
r"Close"
,
"nextMonthTooltip"
:
r"Next month"
,
"previousMonthTooltip"
:
r"Previous month"
},
"de"
:
const
<
String
,
String
>{
"openAppDrawerTooltip"
:
r"Navigationsmenü öffnen"
,
"backButtonTooltip"
:
r"Zurück"
,
"closeButtonTooltip"
:
r"Schließen "
,
"nextMonthTooltip"
:
r"Nächster Monat"
,
"previousMonthTooltip"
:
r"Letzter Monat"
},
"ja"
:
const
<
String
,
String
>{
"openAppDrawerTooltip"
:
r"ナビゲーションメニューを開く"
,
"backButtonTooltip"
:
r"バック"
,
"closeButtonTooltip"
:
r"閉じる"
,
"nextMonthTooltip"
:
r"来月"
,
"previousMonthTooltip"
:
r"前の月"
},
"ru"
:
const
<
String
,
String
>{
"openAppDrawerTooltip"
:
r"Открыть меню навигации"
,
"backButtonTooltip"
:
r"назад"
,
"closeButtonTooltip"
:
r"Закрыть"
,
"nextMonthTooltip"
:
r"В следующем месяце"
,
"previousMonthTooltip"
:
r"Предыдущий месяц"
}
};
packages/flutter/lib/src/material/i18n/material_ar.arb
0 → 100644
View file @
541afae4
{
"openAppDrawerTooltip"
:
"افتح قائمة التنقل"
,
"@openAppDrawerTooltip"
:
{
"description"
:
"The tooltip for the leading AppBar menu (aka 'hamburger') button"
,
"type"
:
"text"
},
"backButtonTooltip"
:
"الى الخلف"
,
"@backButtonTooltip"
:
{
"description"
:
"The BackButton's tooltip"
,
"type"
:
"text"
},
"closeButtonTooltip"
:
"إغلا"
,
"@closeButtonTooltip"
:
{
"description"
:
"The CloseButton's tooltip"
,
"type"
:
"text"
},
"nextMonthTooltip"
:
"الشهر القادم"
,
"@nextMonthTooltip"
:
{
"description"
:
"The tooltip for the MonthPicker's 'next month' button."
,
"type"
:
"text"
},
"previousMonthTooltip"
:
"الشهر الماضى"
,
"@previousMonthTooltip"
:
{
"description"
:
"The tooltip for the MonthPicker's 'previous month' button."
,
"type"
:
"text"
}
}
packages/flutter/lib/src/material/i18n/material_de.arb
0 → 100644
View file @
541afae4
{
"openAppDrawerTooltip"
:
"Navigationsmenü öffnen"
,
"@openAppDrawerTooltip"
:
{
"description"
:
"The tooltip for the leading AppBar menu (aka 'hamburger') button"
,
"type"
:
"text"
},
"backButtonTooltip"
:
"Zurück"
,
"@backButtonTooltip"
:
{
"description"
:
"The BackButton's tooltip"
,
"type"
:
"text"
},
"closeButtonTooltip"
:
"Schließen "
,
"@closeButtonTooltip"
:
{
"description"
:
"The CloseButton's tooltip"
,
"type"
:
"text"
},
"nextMonthTooltip"
:
"Nächster Monat"
,
"@nextMonthTooltip"
:
{
"description"
:
"The tooltip for the MonthPicker's 'next month' button."
,
"type"
:
"text"
},
"previousMonthTooltip"
:
"Letzter Monat"
,
"@previousMonthTooltip"
:
{
"description"
:
"The tooltip for the MonthPicker's 'previous month' button."
,
"type"
:
"text"
}
}
packages/flutter/lib/src/material/i18n/material_en.arb
0 → 100644
View file @
541afae4
{
"openAppDrawerTooltip"
:
"Open navigation menu"
,
"@openAppDrawerTooltip"
:
{
"description"
:
"The tooltip for the leading AppBar menu (aka 'hamburger') button"
,
"type"
:
"text"
},
"backButtonTooltip"
:
"Back"
,
"@backButtonTooltip"
:
{
"description"
:
"The BackButton's tooltip"
,
"type"
:
"text"
},
"closeButtonTooltip"
:
"Close"
,
"@closeButtonTooltip"
:
{
"description"
:
"The CloseButton's tooltip"
,
"type"
:
"text"
},
"nextMonthTooltip"
:
"Next month"
,
"@nextMonthTooltip"
:
{
"description"
:
"The tooltip for the MonthPicker's 'next month' button."
,
"type"
:
"text"
},
"previousMonthTooltip"
:
"Previous month"
,
"@previousMonthTooltip"
:
{
"description"
:
"The tooltip for the MonthPicker's 'previous month' button."
,
"type"
:
"text"
}
}
packages/flutter/lib/src/material/i18n/material_es.arb
0 → 100644
View file @
541afae4
{
"openAppDrawerTooltip"
:
"Abrir el menú de navegación"
,
"@openAppDrawerTooltip"
:
{
"description"
:
"The tooltip for the leading AppBar menu (aka 'hamburger') button"
,
"type"
:
"text"
},
"backButtonTooltip"
:
"Espalda"
,
"@backButtonTooltip"
:
{
"description"
:
"The BackButton's tooltip"
,
"type"
:
"text"
},
"closeButtonTooltip"
:
"Cerrar"
,
"@closeButtonTooltip"
:
{
"description"
:
"The CloseButton's tooltip"
,
"type"
:
"text"
},
"nextMonthTooltip"
:
"Próximo mes"
,
"@nextMonthTooltip"
:
{
"description"
:
"The tooltip for the MonthPicker's 'next month' button."
,
"type"
:
"text"
},
"previousMonthTooltip"
:
"mes anterior"
,
"@previousMonthTooltip"
:
{
"description"
:
"The tooltip for the MonthPicker's 'previous month' button."
,
"type"
:
"text"
}
}
packages/flutter/lib/src/material/i18n/material_fr.arb
0 → 100644
View file @
541afae4
{
"openAppDrawerTooltip"
:
"Ouvrir le menu de navigation"
,
"@openAppDrawerTooltip"
:
{
"description"
:
"The tooltip for the leading AppBar menu (aka 'hamburger') button"
,
"type"
:
"text"
},
"backButtonTooltip"
:
"Arrière"
,
"@backButtonTooltip"
:
{
"description"
:
"The BackButton's tooltip"
,
"type"
:
"text"
},
"closeButtonTooltip"
:
"Fermer"
,
"@closeButtonTooltip"
:
{
"description"
:
"The CloseButton's tooltip"
,
"type"
:
"text"
},
"nextMonthTooltip"
:
"Mois Suivant"
,
"@nextMonthTooltip"
:
{
"description"
:
"The tooltip for the MonthPicker's 'next month' button."
,
"type"
:
"text"
},
"previousMonthTooltip"
:
"Le mois précédent"
,
"@previousMonthTooltip"
:
{
"description"
:
"The tooltip for the MonthPicker's 'previous month' button."
,
"type"
:
"text"
}
}
packages/flutter/lib/src/material/i18n/material_it.arb
0 → 100644
View file @
541afae4
{
"openAppDrawerTooltip"
:
"Apri il menu di navigazione"
,
"@openAppDrawerTooltip"
:
{
"description"
:
"The tooltip for the leading AppBar menu (aka 'hamburger') button"
,
"type"
:
"text"
},
"backButtonTooltip"
:
"Indietro"
,
"@backButtonTooltip"
:
{
"description"
:
"The BackButton's tooltip"
,
"type"
:
"text"
},
"closeButtonTooltip"
:
"Chiudi"
,
"@closeButtonTooltip"
:
{
"description"
:
"The CloseButton's tooltip"
,
"type"
:
"text"
},
"nextMonthTooltip"
:
"Il prossimo mese"
,
"@nextMonthTooltip"
:
{
"description"
:
"The tooltip for the MonthPicker's 'next month' button."
,
"type"
:
"text"
},
"previousMonthTooltip"
:
"Il mese scorso"
,
"@previousMonthTooltip"
:
{
"description"
:
"The tooltip for the MonthPicker's 'previous month' button."
,
"type"
:
"text"
}
}
packages/flutter/lib/src/material/i18n/material_ja.arb
0 → 100644
View file @
541afae4
{
"openAppDrawerTooltip"
:
"ナビゲーションメニューを開く"
,
"@openAppDrawerTooltip"
:
{
"description"
:
"The tooltip for the leading AppBar menu (aka 'hamburger') button"
,
"type"
:
"text"
},
"backButtonTooltip"
:
"バック"
,
"@backButtonTooltip"
:
{
"description"
:
"The BackButton's tooltip"
,
"type"
:
"text"
},
"closeButtonTooltip"
:
"閉じる"
,
"@closeButtonTooltip"
:
{
"description"
:
"The CloseButton's tooltip"
,
"type"
:
"text"
},
"nextMonthTooltip"
:
"来月"
,
"@nextMonthTooltip"
:
{
"description"
:
"The tooltip for the MonthPicker's 'next month' button."
,
"type"
:
"text"
},
"previousMonthTooltip"
:
"前の月"
,
"@previousMonthTooltip"
:
{
"description"
:
"The tooltip for the MonthPicker's 'previous month' button."
,
"type"
:
"text"
}
}
packages/flutter/lib/src/material/i18n/material_pt.arb
0 → 100644
View file @
541afae4
{
"openAppDrawerTooltip"
:
"Abrir menu de navegação"
,
"@openAppDrawerTooltip"
:
{
"description"
:
"The tooltip for the leading AppBar menu (aka 'hamburger') button"
,
"type"
:
"text"
},
"backButtonTooltip"
:
"Costas"
,
"@backButtonTooltip"
:
{
"description"
:
"The BackButton's tooltip"
,
"type"
:
"text"
},
"closeButtonTooltip"
:
"Fechar"
,
"@closeButtonTooltip"
:
{
"description"
:
"The CloseButton's tooltip"
,
"type"
:
"text"
},
"nextMonthTooltip"
:
"Próximo mês"
,
"@nextMonthTooltip"
:
{
"description"
:
"The tooltip for the MonthPicker's 'next month' button."
,
"type"
:
"text"
},
"previousMonthTooltip"
:
"Mês anterior"
,
"@previousMonthTooltip"
:
{
"description"
:
"The tooltip for the MonthPicker's 'previous month' button."
,
"type"
:
"text"
}
}
packages/flutter/lib/src/material/i18n/material_ru.arb
0 → 100644
View file @
541afae4
{
"openAppDrawerTooltip"
:
"Открыть меню навигации"
,
"@openAppDrawerTooltip"
:
{
"description"
:
"The tooltip for the leading AppBar menu (aka 'hamburger') button"
,
"type"
:
"text"
},
"backButtonTooltip"
:
"назад"
,
"@backButtonTooltip"
:
{
"description"
:
"The BackButton's tooltip"
,
"type"
:
"text"
},
"closeButtonTooltip"
:
"Закрыть"
,
"@closeButtonTooltip"
:
{
"description"
:
"The CloseButton's tooltip"
,
"type"
:
"text"
},
"nextMonthTooltip"
:
"В следующем месяце"
,
"@nextMonthTooltip"
:
{
"description"
:
"The tooltip for the MonthPicker's 'next month' button."
,
"type"
:
"text"
},
"previousMonthTooltip"
:
"Предыдущий месяц"
,
"@previousMonthTooltip"
:
{
"description"
:
"The tooltip for the MonthPicker's 'previous month' button."
,
"type"
:
"text"
}
}
packages/flutter/lib/src/material/i18n/material_zh.arb
0 → 100644
View file @
541afae4
{
"openAppDrawerTooltip"
:
"打开导航菜单"
,
"@openAppDrawerTooltip"
:
{
"description"
:
"The tooltip for the leading AppBar menu (aka 'hamburger') button"
,
"type"
:
"text"
},
"backButtonTooltip"
:
"背部"
,
"@backButtonTooltip"
:
{
"description"
:
"The BackButton's tooltip"
,
"type"
:
"text"
},
"closeButtonTooltip"
:
"关"
,
"@closeButtonTooltip"
:
{
"description"
:
"The CloseButton's tooltip"
,
"type"
:
"text"
},
"nextMonthTooltip"
:
"-下月就29了。"
,
"@nextMonthTooltip"
:
{
"description"
:
"The tooltip for the MonthPicker's 'next month' button."
,
"type"
:
"text"
},
"previousMonthTooltip"
:
"前一个月"
,
"@previousMonthTooltip"
:
{
"description"
:
"The tooltip for the MonthPicker's 'previous month' button."
,
"type"
:
"text"
}
}
packages/flutter/lib/src/material/material_localizations.dart
View file @
541afae4
...
...
@@ -2,35 +2,34 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import
'
package:flutter/widgets.dart
'
;
import
'
dart:async
'
;
/// Interface for localized resource values for the material widgets.
///
/// This class provides a default placeholder implementation that returns
/// hard-coded American English values.
class
MaterialLocalizations
{
/// Create a placeholder object for the localized resources of material widgets
/// which only provides American English strings.
const
MaterialLocalizations
();
import
'package:flutter/foundation.dart'
;
import
'package:flutter/widgets.dart'
;
/// The locale for which the values of this class's localized resources
/// have been translated.
Locale
get
locale
=>
const
Locale
(
'en'
,
'US'
);
import
'i18n/localizations.dart'
;
/// Defines the localized resource values used by the Material widgts.
///
/// See also:
///
/// * [DefaultMaterialLocalizations], which implements this interface and
/// and supports a variety of locales.
abstract
class
MaterialLocalizations
{
/// The tooltip for the leading [AppBar] menu (aka 'hamburger') button
String
get
openAppDrawerTooltip
=>
'Open navigation menu'
;
String
get
openAppDrawerTooltip
;
/// The [BackButton]'s tooltip.
String
get
backButtonTooltip
=>
'Back'
;
String
get
backButtonTooltip
;
/// The [CloseButton]'s tooltip.
String
get
closeButtonTooltip
=>
'Close'
;
String
get
closeButtonTooltip
;
/// The tooltip for the [MonthPicker]'s "next month" button.
String
get
nextMonthTooltip
=>
'Next month'
;
String
get
nextMonthTooltip
;
/// The tooltip for the [MonthPicker]'s "previous month" button.
String
get
previousMonthTooltip
=>
'Previous month'
;
String
get
previousMonthTooltip
;
/// The `MaterialLocalizations` from the closest [Localizations] instance
/// that encloses the given context.
...
...
@@ -48,3 +47,46 @@ class MaterialLocalizations {
return
Localizations
.
of
<
MaterialLocalizations
>(
context
,
MaterialLocalizations
);
}
}
/// Localized strings for the material widgets.
class
DefaultMaterialLocalizations
implements
MaterialLocalizations
{
/// Construct an object that defines the material widgets' localized strings
/// for the given `locale`.
DefaultMaterialLocalizations
(
this
.
locale
)
{
assert
(
locale
!=
null
);
_nameToValue
=
localizations
[
locale
.
toString
()]
??
localizations
[
locale
.
languageCode
]
??
localizations
[
'en'
]
??
<
String
,
String
>{};
}
Map
<
String
,
String
>
_nameToValue
;
/// The locale for which the values of this class's localized resources
/// have been translated.
final
Locale
locale
;
@override
String
get
openAppDrawerTooltip
=>
_nameToValue
[
"openAppDrawerTooltip"
];
@override
String
get
backButtonTooltip
=>
_nameToValue
[
"backButtonTooltip"
];
@override
String
get
closeButtonTooltip
=>
_nameToValue
[
"closeButtonTooltip"
];
@override
String
get
nextMonthTooltip
=>
_nameToValue
[
"nextMonthTooltip"
];
@override
String
get
previousMonthTooltip
=>
_nameToValue
[
"previousMonthTooltip"
];
/// Creates an object that provides localized resource values for the
/// for the widgets of the material library.
///
/// This method is typically used to create a [LocalizationsDelegate].
/// The [MaterialApp] does so by default.
static
Future
<
MaterialLocalizations
>
load
(
Locale
locale
)
{
return
new
SynchronousFuture
<
MaterialLocalizations
>(
new
DefaultMaterialLocalizations
(
locale
));
}
}
packages/flutter/lib/src/widgets/localizations.dart
View file @
541afae4
...
...
@@ -16,10 +16,17 @@ import 'framework.dart';
// class Intl { static String message(String s, { String name, String locale }) => ''; }
// Future<Null> initializeMessages(String locale) => null;
// Used by loadAll() to record LocalizationsDelegate.load() futures we're
// waiting for.
class
_Pending
{
_Pending
(
this
.
delegate
,
this
.
futureValue
);
final
LocalizationsDelegate
<
dynamic
>
delegate
;
final
Future
<
dynamic
>
futureValue
;
}
// A utility function used by Localizations to generate one future
// that completes when all of the LocalizationsDelegate.load() futures
// complete. The returned map is indexed by the type of each input
// future's value.
// complete. The returned map is indexed by each delegate's type.
//
// The input future values must have distinct types.
//
...
...
@@ -31,35 +38,38 @@ import 'framework.dart';
// This is more complicated than just applying Future.wait to input
// because some of the input.values may be SynchronousFutures. We don't want
// to Future.wait for the synchronous futures.
Future
<
Map
<
Type
,
dynamic
>>
_loadAll
(
Iterable
<
Future
<
dynamic
>>
inputValu
es
)
{
Future
<
Map
<
Type
,
dynamic
>>
_loadAll
(
Locale
locale
,
Iterable
<
LocalizationsDelegate
<
dynamic
>>
delegat
es
)
{
final
Map
<
Type
,
dynamic
>
output
=
<
Type
,
dynamic
>{};
List
<
Future
<
dynamic
>>
outputFutures
;
List
<
_Pending
>
pendingList
;
for
(
Future
<
dynamic
>
inputValue
in
inputValues
)
{
for
(
LocalizationsDelegate
<
dynamic
>
delegate
in
delegates
)
{
final
Future
<
dynamic
>
inputValue
=
delegate
.
load
(
locale
);
dynamic
completedValue
;
final
Future
<
dynamic
>
futureValue
=
inputValue
.
then
<
dynamic
>((
dynamic
value
)
{
return
completedValue
=
value
;
});
if
(
completedValue
!=
null
)
{
// inputValue was a SynchronousFuture
final
Type
type
=
completedValue
.
runtimeT
ype
;
final
Type
type
=
delegate
.
t
ype
;
assert
(!
output
.
containsKey
(
type
));
output
[
type
]
=
completedValue
;
}
else
{
outputFutures
??=
<
Future
<
dynamic
>
>[];
outputFutures
.
add
(
futureValue
);
pendingList
??=
<
_Pending
>[];
pendingList
.
add
(
new
_Pending
(
delegate
,
futureValue
)
);
}
}
// All of the
input.
values were synchronous futures, we're done.
if
(
outputFutures
==
null
)
// All of the
delegate.load()
values were synchronous futures, we're done.
if
(
pendingList
==
null
)
return
new
SynchronousFuture
<
Map
<
Type
,
dynamic
>>(
output
);
// Some of input.values were asynchronous futures. Wait for them.
return
Future
.
wait
<
dynamic
>(
outputFutures
).
then
<
Map
<
Type
,
dynamic
>>((
List
<
dynamic
>
values
)
{
for
(
dynamic
value
in
values
)
{
final
Type
type
=
value
.
runtimeType
;
// Some of delegate.load() values were asynchronous futures. Wait for them.
return
Future
.
wait
<
dynamic
>(
pendingList
.
map
((
_Pending
p
)
=>
p
.
futureValue
))
.
then
<
Map
<
Type
,
dynamic
>>((
List
<
dynamic
>
values
)
{
assert
(
values
.
length
==
pendingList
.
length
);
for
(
int
i
=
0
;
i
<
values
.
length
;
i
+=
1
)
{
final
Type
type
=
pendingList
[
i
].
delegate
.
type
;
assert
(!
output
.
containsKey
(
type
));
output
[
type
]
=
value
;
output
[
type
]
=
values
[
i
]
;
}
return
output
;
});
...
...
@@ -92,8 +102,10 @@ abstract class LocalizationsDelegate<T> {
/// after [load] has completed.
bool
shouldReload
(
covariant
LocalizationsDelegate
<
T
>
old
);
Type
get
type
=>
T
;
@override
String
toString
()
=>
'
$runtimeType
'
;
String
toString
()
=>
'
$runtimeType
[
$type
]
'
;
}
/// Interface for localized resource values for the lowest levels of the Flutter
...
...
@@ -346,12 +358,8 @@ class _LocalizationsState extends State<Localizations> {
return
;
}
final
Iterable
<
Future
<
dynamic
>>
allResources
=
delegates
.
map
((
LocalizationsDelegate
<
dynamic
>
delegate
)
{
return
delegate
.
load
(
locale
);
});
Map
<
Type
,
dynamic
>
typeToResources
;
final
Future
<
Map
<
Type
,
dynamic
>>
typeToResourcesFuture
=
_loadAll
(
allResourc
es
)
final
Future
<
Map
<
Type
,
dynamic
>>
typeToResourcesFuture
=
_loadAll
(
locale
,
delegat
es
)
.
then
((
Map
<
Type
,
dynamic
>
value
)
{
return
typeToResources
=
value
;
});
...
...
@@ -383,7 +391,6 @@ class _LocalizationsState extends State<Localizations> {
T
resourcesFor
<
T
>(
Type
type
)
{
assert
(
type
!=
null
);
final
T
resources
=
_typeToResources
[
type
];
assert
(
resources
.
runtimeType
==
type
);
return
resources
;
}
...
...
packages/flutter/test/material/localizations_test.dart
0 → 100644
View file @
541afae4
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import
'package:flutter/material.dart'
;
import
'package:flutter_test/flutter_test.dart'
;
Widget
buildFrame
(
{
Locale
locale
,
WidgetBuilder
buildContent
,
})
{
return
new
MaterialApp
(
color:
const
Color
(
0xFFFFFFFF
),
locale:
locale
,
onGenerateRoute:
(
RouteSettings
settings
)
{
return
new
MaterialPageRoute
<
Null
>(
builder:
(
BuildContext
context
)
{
return
buildContent
(
context
);
}
);
},
);
}
void
main
(
)
{
final
Key
textKey
=
new
UniqueKey
();
testWidgets
(
'sanity check'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
buildFrame
(
buildContent:
(
BuildContext
context
)
{
return
new
Text
(
MaterialLocalizations
.
of
(
context
).
backButtonTooltip
,
key:
textKey
,
);
}
)
);
expect
(
tester
.
widget
<
Text
>(
find
.
byKey
(
textKey
)).
data
,
'Back'
);
// Spanish Bolivia locale, falls back to just 'es'
await
tester
.
binding
.
setLocale
(
'es'
,
'bo'
);
await
tester
.
pump
();
expect
(
tester
.
widget
<
Text
>(
find
.
byKey
(
textKey
)).
data
,
'Espalda'
);
// Unrecognized locale falls back to 'en'
await
tester
.
binding
.
setLocale
(
'foo'
,
'bar'
);
await
tester
.
pump
();
expect
(
tester
.
widget
<
Text
>(
find
.
byKey
(
textKey
)).
data
,
'Back'
);
});
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment