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
4451ffca
Unverified
Commit
4451ffca
authored
Apr 09, 2020
by
Per Classon
Committed by
GitHub
Apr 09, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add option for deferred loading to gen_l10n (#53824)
parent
0d459f23
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
309 additions
and
54 deletions
+309
-54
gen_l10n.dart
dev/tools/localization/bin/gen_l10n.dart
+20
-0
gen_l10n.dart
dev/tools/localization/gen_l10n.dart
+130
-31
gen_l10n_templates.dart
dev/tools/localization/gen_l10n_templates.dart
+56
-21
gen_l10n_test.dart
dev/tools/test/localization/gen_l10n_test.dart
+83
-0
gen_l10n_test.dart
...s/flutter_tools/test/integration.shard/gen_l10n_test.dart
+20
-2
No files found.
dev/tools/localization/bin/gen_l10n.dart
View file @
4451ffca
...
@@ -81,6 +81,24 @@ void main(List<String> arguments) {
...
@@ -81,6 +81,24 @@ void main(List<String> arguments) {
'Alternatively, see the `header` option to pass in a string '
'Alternatively, see the `header` option to pass in a string '
'for a simpler header.'
'for a simpler header.'
);
);
parser
.
addFlag
(
'use-deferred-loading'
,
defaultsTo:
false
,
help:
'Whether to generate the Dart localization file with locales imported'
' as deferred, allowing for lazy loading of each locale in Flutter web.
\n
'
'
\n
'
'This can reduce a web app’s initial startup time by decreasing the '
'size of the JavaScript bundle. When this flag is set to true, the '
'messages for a particular locale are only downloaded and loaded by the '
'Flutter app as they are needed. For projects with a lot of different '
'locales and many localization strings, it can be an performance '
'improvement to have deferred loading. For projects with a small number '
'of locales, the difference is negligible, and might slow down the start '
'up compared to bundling the localizations with the rest of the '
'application.
\n\n
'
'Note that this flag does not affect other platforms such as mobile or '
'desktop.'
,
);
final
argslib
.
ArgResults
results
=
parser
.
parse
(
arguments
);
final
argslib
.
ArgResults
results
=
parser
.
parse
(
arguments
);
if
(
results
[
'help'
]
==
true
)
{
if
(
results
[
'help'
]
==
true
)
{
...
@@ -98,6 +116,7 @@ void main(List<String> arguments) {
...
@@ -98,6 +116,7 @@ void main(List<String> arguments) {
final
String
preferredSupportedLocaleString
=
results
[
'preferred-supported-locales'
]
as
String
;
final
String
preferredSupportedLocaleString
=
results
[
'preferred-supported-locales'
]
as
String
;
final
String
headerString
=
results
[
'header'
]
as
String
;
final
String
headerString
=
results
[
'header'
]
as
String
;
final
String
headerFile
=
results
[
'header-file'
]
as
String
;
final
String
headerFile
=
results
[
'header-file'
]
as
String
;
final
bool
useDeferredLoading
=
results
[
'use-deferred-loading'
]
as
bool
;
const
local
.
LocalFileSystem
fs
=
local
.
LocalFileSystem
();
const
local
.
LocalFileSystem
fs
=
local
.
LocalFileSystem
();
final
LocalizationsGenerator
localizationsGenerator
=
LocalizationsGenerator
(
fs
);
final
LocalizationsGenerator
localizationsGenerator
=
LocalizationsGenerator
(
fs
);
...
@@ -112,6 +131,7 @@ void main(List<String> arguments) {
...
@@ -112,6 +131,7 @@ void main(List<String> arguments) {
preferredSupportedLocaleString:
preferredSupportedLocaleString
,
preferredSupportedLocaleString:
preferredSupportedLocaleString
,
headerString:
headerString
,
headerString:
headerString
,
headerFile:
headerFile
,
headerFile:
headerFile
,
useDeferredLoading:
useDeferredLoading
,
)
)
..
loadResources
()
..
loadResources
()
..
writeOutputFile
()
..
writeOutputFile
()
...
...
dev/tools/localization/gen_l10n.dart
View file @
4451ffca
...
@@ -206,7 +206,10 @@ String generateBaseClassMethod(Message message) {
...
@@ -206,7 +206,10 @@ String generateBaseClassMethod(Message message) {
.
replaceAll
(
'@(name)'
,
message
.
resourceId
);
.
replaceAll
(
'@(name)'
,
message
.
resourceId
);
}
}
String
_generateLookupByAllCodes
(
AppResourceBundleCollection
allBundles
,
String
className
)
{
String
_generateLookupByAllCodes
(
AppResourceBundleCollection
allBundles
,
String
Function
(
LocaleInfo
)
generateSwitchClauseTemplate
,
)
{
final
Iterable
<
LocaleInfo
>
localesWithAllCodes
=
allBundles
.
locales
.
where
((
LocaleInfo
locale
)
{
final
Iterable
<
LocaleInfo
>
localesWithAllCodes
=
allBundles
.
locales
.
where
((
LocaleInfo
locale
)
{
return
locale
.
scriptCode
!=
null
&&
locale
.
countryCode
!=
null
;
return
locale
.
scriptCode
!=
null
&&
locale
.
countryCode
!=
null
;
});
});
...
@@ -216,9 +219,8 @@ String _generateLookupByAllCodes(AppResourceBundleCollection allBundles, String
...
@@ -216,9 +219,8 @@ String _generateLookupByAllCodes(AppResourceBundleCollection allBundles, String
}
}
final
Iterable
<
String
>
switchClauses
=
localesWithAllCodes
.
map
<
String
>((
LocaleInfo
locale
)
{
final
Iterable
<
String
>
switchClauses
=
localesWithAllCodes
.
map
<
String
>((
LocaleInfo
locale
)
{
return
switchClauseTemplate
return
generateSwitchClauseTemplate
(
locale
)
.
replaceAll
(
'@(case)'
,
locale
.
toString
())
.
replaceAll
(
'@(case)'
,
locale
.
toString
());
.
replaceAll
(
'@(class)'
,
'
$className${locale.camelCase()}
'
);
});
});
return
allCodesLookupTemplate
.
replaceAll
(
return
allCodesLookupTemplate
.
replaceAll
(
...
@@ -227,7 +229,10 @@ String _generateLookupByAllCodes(AppResourceBundleCollection allBundles, String
...
@@ -227,7 +229,10 @@ String _generateLookupByAllCodes(AppResourceBundleCollection allBundles, String
);
);
}
}
String
_generateLookupByScriptCode
(
AppResourceBundleCollection
allBundles
,
String
className
)
{
String
_generateLookupByScriptCode
(
AppResourceBundleCollection
allBundles
,
String
Function
(
LocaleInfo
)
generateSwitchClauseTemplate
,
)
{
final
Iterable
<
String
>
switchClauses
=
allBundles
.
languages
.
map
((
String
language
)
{
final
Iterable
<
String
>
switchClauses
=
allBundles
.
languages
.
map
((
String
language
)
{
final
Iterable
<
LocaleInfo
>
locales
=
allBundles
.
localesForLanguage
(
language
);
final
Iterable
<
LocaleInfo
>
locales
=
allBundles
.
localesForLanguage
(
language
);
final
Iterable
<
LocaleInfo
>
localesWithScriptCodes
=
locales
.
where
((
LocaleInfo
locale
)
{
final
Iterable
<
LocaleInfo
>
localesWithScriptCodes
=
locales
.
where
((
LocaleInfo
locale
)
{
...
@@ -240,11 +245,9 @@ String _generateLookupByScriptCode(AppResourceBundleCollection allBundles, Strin
...
@@ -240,11 +245,9 @@ String _generateLookupByScriptCode(AppResourceBundleCollection allBundles, Strin
return
nestedSwitchTemplate
return
nestedSwitchTemplate
.
replaceAll
(
'@(languageCode)'
,
language
)
.
replaceAll
(
'@(languageCode)'
,
language
)
.
replaceAll
(
'@(code)'
,
'scriptCode'
)
.
replaceAll
(
'@(code)'
,
'scriptCode'
)
.
replaceAll
(
'@(class)'
,
'
$className${LocaleInfo.fromString(language).camelCase()}
'
)
.
replaceAll
(
'@(switchClauses)'
,
localesWithScriptCodes
.
map
((
LocaleInfo
locale
)
{
.
replaceAll
(
'@(switchClauses)'
,
localesWithScriptCodes
.
map
((
LocaleInfo
locale
)
{
return
switchClauseTemplate
return
generateSwitchClauseTemplate
(
locale
)
.
replaceAll
(
'@(case)'
,
locale
.
scriptCode
)
.
replaceAll
(
'@(case)'
,
locale
.
scriptCode
);
.
replaceAll
(
'@(class)'
,
'
$className${locale.camelCase()}
'
);
}).
join
(
'
\n
'
));
}).
join
(
'
\n
'
));
}).
where
((
String
switchClause
)
=>
switchClause
!=
null
);
}).
where
((
String
switchClause
)
=>
switchClause
!=
null
);
...
@@ -258,7 +261,10 @@ String _generateLookupByScriptCode(AppResourceBundleCollection allBundles, Strin
...
@@ -258,7 +261,10 @@ String _generateLookupByScriptCode(AppResourceBundleCollection allBundles, Strin
);
);
}
}
String
_generateLookupByCountryCode
(
AppResourceBundleCollection
allBundles
,
String
className
)
{
String
_generateLookupByCountryCode
(
AppResourceBundleCollection
allBundles
,
String
Function
(
LocaleInfo
)
generateSwitchClauseTemplate
,
)
{
final
Iterable
<
String
>
switchClauses
=
allBundles
.
languages
.
map
((
String
language
)
{
final
Iterable
<
String
>
switchClauses
=
allBundles
.
languages
.
map
((
String
language
)
{
final
Iterable
<
LocaleInfo
>
locales
=
allBundles
.
localesForLanguage
(
language
);
final
Iterable
<
LocaleInfo
>
locales
=
allBundles
.
localesForLanguage
(
language
);
final
Iterable
<
LocaleInfo
>
localesWithCountryCodes
=
locales
.
where
((
LocaleInfo
locale
)
{
final
Iterable
<
LocaleInfo
>
localesWithCountryCodes
=
locales
.
where
((
LocaleInfo
locale
)
{
...
@@ -271,11 +277,9 @@ String _generateLookupByCountryCode(AppResourceBundleCollection allBundles, Stri
...
@@ -271,11 +277,9 @@ String _generateLookupByCountryCode(AppResourceBundleCollection allBundles, Stri
return
nestedSwitchTemplate
return
nestedSwitchTemplate
.
replaceAll
(
'@(languageCode)'
,
language
)
.
replaceAll
(
'@(languageCode)'
,
language
)
.
replaceAll
(
'@(code)'
,
'countryCode'
)
.
replaceAll
(
'@(code)'
,
'countryCode'
)
.
replaceAll
(
'@(class)'
,
'
$className${LocaleInfo.fromString(language).camelCase()}
'
)
.
replaceAll
(
'@(switchClauses)'
,
localesWithCountryCodes
.
map
((
LocaleInfo
locale
)
{
.
replaceAll
(
'@(switchClauses)'
,
localesWithCountryCodes
.
map
((
LocaleInfo
locale
)
{
return
switchClauseTemplate
return
generateSwitchClauseTemplate
(
locale
)
.
replaceAll
(
'@(case)'
,
locale
.
countryCode
)
.
replaceAll
(
'@(case)'
,
locale
.
countryCode
);
.
replaceAll
(
'@(class)'
,
'
$className${locale.camelCase()}
'
);
}).
join
(
'
\n
'
));
}).
join
(
'
\n
'
));
}).
where
((
String
switchClause
)
=>
switchClause
!=
null
);
}).
where
((
String
switchClause
)
=>
switchClause
!=
null
);
...
@@ -288,7 +292,10 @@ String _generateLookupByCountryCode(AppResourceBundleCollection allBundles, Stri
...
@@ -288,7 +292,10 @@ String _generateLookupByCountryCode(AppResourceBundleCollection allBundles, Stri
.
replaceAll
(
'@(switchClauses)'
,
switchClauses
.
join
(
'
\n
'
));
.
replaceAll
(
'@(switchClauses)'
,
switchClauses
.
join
(
'
\n
'
));
}
}
String
_generateLookupByLanguageCode
(
AppResourceBundleCollection
allBundles
,
String
className
)
{
String
_generateLookupByLanguageCode
(
AppResourceBundleCollection
allBundles
,
String
Function
(
LocaleInfo
)
generateSwitchClauseTemplate
,
)
{
final
Iterable
<
String
>
switchClauses
=
allBundles
.
languages
.
map
((
String
language
)
{
final
Iterable
<
String
>
switchClauses
=
allBundles
.
languages
.
map
((
String
language
)
{
final
Iterable
<
LocaleInfo
>
locales
=
allBundles
.
localesForLanguage
(
language
);
final
Iterable
<
LocaleInfo
>
locales
=
allBundles
.
localesForLanguage
(
language
);
final
Iterable
<
LocaleInfo
>
localesWithLanguageCode
=
locales
.
where
((
LocaleInfo
locale
)
{
final
Iterable
<
LocaleInfo
>
localesWithLanguageCode
=
locales
.
where
((
LocaleInfo
locale
)
{
...
@@ -299,9 +306,8 @@ String _generateLookupByLanguageCode(AppResourceBundleCollection allBundles, Str
...
@@ -299,9 +306,8 @@ String _generateLookupByLanguageCode(AppResourceBundleCollection allBundles, Str
return
null
;
return
null
;
return
localesWithLanguageCode
.
map
((
LocaleInfo
locale
)
{
return
localesWithLanguageCode
.
map
((
LocaleInfo
locale
)
{
return
switchClauseTemplate
return
generateSwitchClauseTemplate
(
locale
)
.
replaceAll
(
'@(case)'
,
locale
.
languageCode
)
.
replaceAll
(
'@(case)'
,
locale
.
languageCode
);
.
replaceAll
(
'@(class)'
,
'
$className${locale.camelCase()}
'
);
}).
join
(
'
\n
'
);
}).
join
(
'
\n
'
);
}).
where
((
String
switchClause
)
=>
switchClause
!=
null
);
}).
where
((
String
switchClause
)
=>
switchClause
!=
null
);
...
@@ -314,12 +320,67 @@ String _generateLookupByLanguageCode(AppResourceBundleCollection allBundles, Str
...
@@ -314,12 +320,67 @@ String _generateLookupByLanguageCode(AppResourceBundleCollection allBundles, Str
.
replaceAll
(
'@(switchClauses)'
,
switchClauses
.
join
(
'
\n
'
));
.
replaceAll
(
'@(switchClauses)'
,
switchClauses
.
join
(
'
\n
'
));
}
}
String
_generateLookupBody
(
AppResourceBundleCollection
allBundles
,
String
className
)
{
String
_generateLookupBody
(
AppResourceBundleCollection
allBundles
,
String
className
,
bool
useDeferredLoading
,
String
fileName
,
)
{
final
String
Function
(
LocaleInfo
)
generateSwitchClauseTemplate
=
(
LocaleInfo
locale
)
{
return
(
useDeferredLoading
?
switchClauseDeferredLoadingTemplate
:
switchClauseTemplate
)
.
replaceAll
(
'@(localeClass)'
,
'
$className${locale.camelCase()}
'
)
.
replaceAll
(
'@(appClass)'
,
className
)
.
replaceAll
(
'@(library)'
,
'
${fileName}
_
${locale.languageCode}
'
);
};
return
lookupBodyTemplate
return
lookupBodyTemplate
.
replaceAll
(
'@(lookupAllCodesSpecified)'
,
_generateLookupByAllCodes
(
allBundles
,
className
))
.
replaceAll
(
'@(lookupAllCodesSpecified)'
,
_generateLookupByAllCodes
(
.
replaceAll
(
'@(lookupScriptCodeSpecified)'
,
_generateLookupByScriptCode
(
allBundles
,
className
))
allBundles
,
.
replaceAll
(
'@(lookupCountryCodeSpecified)'
,
_generateLookupByCountryCode
(
allBundles
,
className
))
generateSwitchClauseTemplate
,
.
replaceAll
(
'@(lookupLanguageCodeSpecified)'
,
_generateLookupByLanguageCode
(
allBundles
,
className
));
))
.
replaceAll
(
'@(lookupScriptCodeSpecified)'
,
_generateLookupByScriptCode
(
allBundles
,
generateSwitchClauseTemplate
,
))
.
replaceAll
(
'@(lookupCountryCodeSpecified)'
,
_generateLookupByCountryCode
(
allBundles
,
generateSwitchClauseTemplate
,
))
.
replaceAll
(
'@(lookupLanguageCodeSpecified)'
,
_generateLookupByLanguageCode
(
allBundles
,
generateSwitchClauseTemplate
,
));
}
String
_generateDelegateClass
(
{
AppResourceBundleCollection
allBundles
,
String
className
,
Set
<
String
>
supportedLanguageCodes
,
bool
useDeferredLoading
,
String
fileName
,
})
{
final
String
lookupBody
=
_generateLookupBody
(
allBundles
,
className
,
useDeferredLoading
,
fileName
,
);
final
String
loadBody
=
(
useDeferredLoading
?
loadBodyDeferredLoadingTemplate
:
loadBodyTemplate
)
.
replaceAll
(
'@(class)'
,
className
)
.
replaceAll
(
'@(lookupName)'
,
'_lookup
$className
'
);
final
String
lookupFunction
=
(
useDeferredLoading
?
lookupFunctionDeferredLoadingTemplate
:
lookupFunctionTemplate
)
.
replaceAll
(
'@(class)'
,
className
)
.
replaceAll
(
'@(lookupName)'
,
'_lookup
$className
'
)
.
replaceAll
(
'@(lookupBody)'
,
lookupBody
);
return
delegateClassTemplate
.
replaceAll
(
'@(class)'
,
className
)
.
replaceAll
(
'@(loadBody)'
,
loadBody
)
.
replaceAll
(
'@(supportedLanguageCodes)'
,
supportedLanguageCodes
.
join
(
', '
))
.
replaceAll
(
'@(lookupFunction)'
,
lookupFunction
);
}
}
class
LocalizationsGenerator
{
class
LocalizationsGenerator
{
...
@@ -397,6 +458,23 @@ class LocalizationsGenerator {
...
@@ -397,6 +458,23 @@ class LocalizationsGenerator {
final
Map
<
LocaleInfo
,
List
<
String
>>
_unimplementedMessages
=
<
LocaleInfo
,
List
<
String
>>{};
final
Map
<
LocaleInfo
,
List
<
String
>>
_unimplementedMessages
=
<
LocaleInfo
,
List
<
String
>>{};
/// Whether to generate the Dart localization file with locales imported as
/// deferred, allowing for lazy loading of each locale in Flutter web.
///
/// This can reduce a web app’s initial startup time by decreasing the size of
/// the JavaScript bundle. When [_useDeferredLoading] is set to true, the
/// messages for a particular locale are only downloaded and loaded by the
/// Flutter app as they are needed. For projects with a lot of different
/// locales and many localization strings, it can be an performance
/// improvement to have deferred loading. For projects with a small number of
/// locales, the difference is negligible, and might slow down the start up
/// compared to bundling the localizations with the rest of the application.
///
/// Note that this flag does not affect other platforms such as mobile or
/// desktop.
bool
get
useDeferredLoading
=>
_useDeferredLoading
;
bool
_useDeferredLoading
;
/// Initializes [l10nDirectory], [templateArbFile], [outputFile] and [className].
/// Initializes [l10nDirectory], [templateArbFile], [outputFile] and [className].
///
///
/// Throws an [L10nException] when a provided configuration is not allowed
/// Throws an [L10nException] when a provided configuration is not allowed
...
@@ -412,12 +490,14 @@ class LocalizationsGenerator {
...
@@ -412,12 +490,14 @@ class LocalizationsGenerator {
String
preferredSupportedLocaleString
,
String
preferredSupportedLocaleString
,
String
headerString
,
String
headerString
,
String
headerFile
,
String
headerFile
,
bool
useDeferredLoading
=
false
,
})
{
})
{
setL10nDirectory
(
l10nDirectoryPath
);
setL10nDirectory
(
l10nDirectoryPath
);
setTemplateArbFile
(
templateArbFileName
);
setTemplateArbFile
(
templateArbFileName
);
setOutputFile
(
outputFileString
);
setOutputFile
(
outputFileString
);
setPreferredSupportedLocales
(
preferredSupportedLocaleString
);
setPreferredSupportedLocales
(
preferredSupportedLocaleString
);
_setHeader
(
headerString
,
headerFile
);
_setHeader
(
headerString
,
headerFile
);
_setUseDeferredLoading
(
useDeferredLoading
);
className
=
classNameString
;
className
=
classNameString
;
}
}
...
@@ -550,6 +630,13 @@ class LocalizationsGenerator {
...
@@ -550,6 +630,13 @@ class LocalizationsGenerator {
}
}
}
}
void
_setUseDeferredLoading
(
bool
useDeferredLoading
)
{
if
(
useDeferredLoading
==
null
)
{
throw
L10nException
(
'useDeferredLoading argument cannot be null.'
);
}
_useDeferredLoading
=
useDeferredLoading
;
}
static
bool
_isValidGetterAndMethodName
(
String
name
)
{
static
bool
_isValidGetterAndMethodName
(
String
name
)
{
// Public Dart method name must not start with an underscore
// Public Dart method name must not start with an underscore
if
(
name
[
0
]
==
'_'
)
if
(
name
[
0
]
==
'_'
)
...
@@ -746,13 +833,26 @@ class LocalizationsGenerator {
...
@@ -746,13 +833,26 @@ class LocalizationsGenerator {
}
}
}
}
final
Iterable
<
String
>
locale
Imports
=
supportedLocales
final
List
<
String
>
sortedClass
Imports
=
supportedLocales
.
where
((
LocaleInfo
locale
)
=>
isBaseClassLocale
(
locale
,
locale
.
languageCode
))
.
where
((
LocaleInfo
locale
)
=>
isBaseClassLocale
(
locale
,
locale
.
languageCode
))
.
map
((
LocaleInfo
locale
)
{
.
map
((
LocaleInfo
locale
)
{
return
"import '
${fileName}
_
${locale.toString()}
.dart';"
;
final
String
library
=
'
${fileName}
_
${locale.toString()}
'
;
});
if
(
useDeferredLoading
)
{
return
"import '
$library
.dart' deferred as
$library
;"
;
final
String
lookupBody
=
_generateLookupBody
(
_allBundles
,
className
);
}
else
{
return
"import '
$library
.dart';"
;
}
})
.
toList
()
..
sort
();
final
String
delegateClass
=
_generateDelegateClass
(
allBundles:
_allBundles
,
className:
className
,
supportedLanguageCodes:
supportedLanguageCodes
,
useDeferredLoading:
useDeferredLoading
,
fileName:
fileName
,
);
return
fileTemplate
return
fileTemplate
.
replaceAll
(
'@(header)'
,
header
)
.
replaceAll
(
'@(header)'
,
header
)
...
@@ -761,9 +861,8 @@ class LocalizationsGenerator {
...
@@ -761,9 +861,8 @@ class LocalizationsGenerator {
.
replaceAll
(
'@(importFile)'
,
'
$directory
/
$outputFileName
'
)
.
replaceAll
(
'@(importFile)'
,
'
$directory
/
$outputFileName
'
)
.
replaceAll
(
'@(supportedLocales)'
,
supportedLocalesCode
.
join
(
',
\n
'
))
.
replaceAll
(
'@(supportedLocales)'
,
supportedLocalesCode
.
join
(
',
\n
'
))
.
replaceAll
(
'@(supportedLanguageCodes)'
,
supportedLanguageCodes
.
join
(
', '
))
.
replaceAll
(
'@(supportedLanguageCodes)'
,
supportedLanguageCodes
.
join
(
', '
))
.
replaceAll
(
'@(messageClassImports)'
,
localeImports
.
join
(
'
\n
'
))
.
replaceAll
(
'@(messageClassImports)'
,
sortedClassImports
.
join
(
'
\n
'
))
.
replaceAll
(
'@(lookupName)'
,
'_lookup
$className
'
)
.
replaceAll
(
'@(delegateClass)'
,
delegateClass
);
.
replaceAll
(
'@(lookupBody)'
,
lookupBody
);
}
}
void
writeOutputFile
()
{
void
writeOutputFile
()
{
...
...
dev/tools/localization/gen_l10n_templates.dart
View file @
4451ffca
...
@@ -6,6 +6,7 @@ const String fileTemplate = '''
...
@@ -6,6 +6,7 @@ const String fileTemplate = '''
@(header)
@(header)
import '
dart:
async
';
import '
dart:
async
';
// ignore: unused_import
import '
package:
flutter
/
foundation
.
dart
';
import '
package:
flutter
/
foundation
.
dart
';
import '
package:
flutter
/
widgets
.
dart
';
import '
package:
flutter
/
widgets
.
dart
';
import '
package:
flutter_localizations
/
flutter_localizations
.
dart
';
import '
package:
flutter_localizations
/
flutter_localizations
.
dart
';
...
@@ -104,26 +105,7 @@ abstract class @(class) {
...
@@ -104,26 +105,7 @@ abstract class @(class) {
@
(
methods
)}
@
(
methods
)}
class
_
@
(
class
)
Delegate
extends
LocalizationsDelegate
<
@
(
class
)>
{
@
(
delegateClass
)
const
_
@
(
class
)
Delegate
();
@override
Future
<
@
(
class
)>
load
(
Locale
locale
)
{
return
SynchronousFuture
<
@
(
class
)>(@(
lookupName
)(
locale
));
}
@override
bool
isSupported
(
Locale
locale
)
=>
<
String
>[
@
(
supportedLanguageCodes
)].
contains
(
locale
.
languageCode
);
@override
bool
shouldReload
(
_
@
(
class
)
Delegate
old
)
=>
false
;
}
@
(
class
)
@(
lookupName
)(
Locale
locale
)
{
@
(
lookupBody
)
assert
(
false
,
'@(class).delegate failed to load unsupported locale "
\
$locale
"'
);
return
null
;
}
''';
''';
const String numberFormatTemplate = '''
const String numberFormatTemplate = '''
...
@@ -205,14 +187,67 @@ const String baseClassMethodTemplate = '''
...
@@ -205,14 +187,67 @@ const String baseClassMethodTemplate = '''
String
@
(
name
)(
@
(
parameters
));
String
@
(
name
)(
@
(
parameters
));
''';
''';
// DELEGATE CLASS TEMPLATES
const String delegateClassTemplate = '''
class
_
@
(
class
)
Delegate
extends
LocalizationsDelegate
<
@
(
class
)>
{
const
_
@
(
class
)
Delegate
();
@override
Future
<
@
(
class
)>
load
(
Locale
locale
)
{
@
(
loadBody
)
}
@override
bool
isSupported
(
Locale
locale
)
=>
<
String
>[
@
(
supportedLanguageCodes
)].
contains
(
locale
.
languageCode
);
@override
bool
shouldReload
(
_
@
(
class
)
Delegate
old
)
=>
false
;
}
@
(
lookupFunction
)
''';
const String loadBodyTemplate = '''
return
SynchronousFuture
<
@
(
class
)>(@(
lookupName
)(
locale
));
''';
const String loadBodyDeferredLoadingTemplate = '''
return
@
(
lookupName
)(
locale
);
''';
// DELEGATE LOOKUP TEMPLATES
// DELEGATE LOOKUP TEMPLATES
const String lookupFunctionTemplate = '''
@
(
class
)
@(
lookupName
)(
Locale
locale
)
{
@
(
lookupBody
)
assert
(
false
,
'@(class).delegate failed to load unsupported locale "
\
$locale
"'
);
return
null
;
}
''';
const String lookupFunctionDeferredLoadingTemplate = '''
/// Lazy load the library for web, on other platforms we return the
/// localizations synchronously.
Future
<
@
(
class
)>
_loadLibraryForWeb
(
Future
<
dynamic
>
Function
()
loadLibrary
,
@
(
class
)
Function
()
localizationClosure
,
)
{
if
(
kIsWeb
)
{
return
loadLibrary
().
then
((
dynamic
_
)
=>
localizationClosure
());
}
else
{
return
SynchronousFuture
<
@
(
class
)>(
localizationClosure
());
}
}
Future
<
@
(
class
)>
@(
lookupName
)(
Locale
locale
)
{
@
(
lookupBody
)
assert
(
false
,
'@(class).delegate failed to load unsupported locale "
\
$locale
"'
);
return
null
;
}
''';
const String lookupBodyTemplate = '''
@
(
lookupAllCodesSpecified
)
const String lookupBodyTemplate = '''
@
(
lookupAllCodesSpecified
)
@
(
lookupScriptCodeSpecified
)
@
(
lookupScriptCodeSpecified
)
@
(
lookupCountryCodeSpecified
)
@
(
lookupCountryCodeSpecified
)
@
(
lookupLanguageCodeSpecified
)
''';
@
(
lookupLanguageCodeSpecified
)
''';
const String switchClauseTemplate = '''
case
'@(case)'
:
return
@
(
class
)();''';
const String switchClauseTemplate = '''
case
'@(case)'
:
return
@
(
localeClass
)();
''';
const String switchClauseDeferredLoadingTemplate = '''
case
'@(case)'
:
return
_loadLibraryForWeb
(
@
(
library
).
loadLibrary
,
()
=>
@
(
library
).
@
(
localeClass
)());
''';
const String nestedSwitchTemplate = '''
case
'@(languageCode)'
:
{
const String nestedSwitchTemplate = '''
case
'@(languageCode)'
:
{
switch
(
locale
.
@
(
code
))
{
switch
(
locale
.
@
(
code
))
{
...
...
dev/tools/test/localization/gen_l10n_test.dart
View file @
4451ffca
...
@@ -380,6 +380,28 @@ void main() {
...
@@ -380,6 +380,28 @@ void main() {
fail
(
'Setting headerFile that does not exist should fail'
);
fail
(
'Setting headerFile that does not exist should fail'
);
});
});
test
(
'setting useDefferedLoading to null should fail'
,
()
{
_standardFlutterDirectoryL10nSetup
(
fs
);
LocalizationsGenerator
generator
;
try
{
generator
=
LocalizationsGenerator
(
fs
);
generator
.
initialize
(
l10nDirectoryPath:
defaultArbPathString
,
templateArbFileName:
defaultTemplateArbFileName
,
outputFileString:
defaultOutputFileString
,
classNameString:
defaultClassNameString
,
headerString:
'/// Sample header'
,
useDeferredLoading:
null
,
);
}
on
L10nException
catch
(
e
)
{
expect
(
e
.
message
,
contains
(
'useDeferredLoading argument cannot be null.'
));
return
;
}
fail
(
'Setting useDefferedLoading to null should fail'
);
});
group
(
'loadResources'
,
()
{
group
(
'loadResources'
,
()
{
test
(
'correctly initializes supportedLocales and supportedLanguageCodes properties'
,
()
{
test
(
'correctly initializes supportedLocales and supportedLanguageCodes properties'
,
()
{
_standardFlutterDirectoryL10nSetup
(
fs
);
_standardFlutterDirectoryL10nSetup
(
fs
);
...
@@ -792,6 +814,67 @@ void main() {
...
@@ -792,6 +814,67 @@ void main() {
expect
(
englishLocalizationsFile
,
contains
(
'class AppLocalizationsEn extends AppLocalizations'
));
expect
(
englishLocalizationsFile
,
contains
(
'class AppLocalizationsEn extends AppLocalizations'
));
});
});
test
(
'language imports are sorted when preferredSupportedLocaleString is given'
,
()
{
fs
.
currentDirectory
.
childDirectory
(
'lib'
).
childDirectory
(
'l10n'
)..
createSync
(
recursive:
true
)
..
childFile
(
defaultTemplateArbFileName
).
writeAsStringSync
(
singleMessageArbFileString
)
..
childFile
(
'app_zh.arb'
).
writeAsStringSync
(
singleZhMessageArbFileString
)
..
childFile
(
'app_es.arb'
).
writeAsStringSync
(
singleEsMessageArbFileString
);
const
String
preferredSupportedLocaleString
=
'["zh"]'
;
final
LocalizationsGenerator
generator
=
LocalizationsGenerator
(
fs
);
try
{
generator
.
initialize
(
l10nDirectoryPath:
defaultArbPathString
,
templateArbFileName:
defaultTemplateArbFileName
,
outputFileString:
defaultOutputFileString
,
classNameString:
defaultClassNameString
,
preferredSupportedLocaleString:
preferredSupportedLocaleString
,
);
generator
.
loadResources
();
generator
.
writeOutputFile
();
}
on
Exception
catch
(
e
)
{
fail
(
'Generating output files should not fail:
$e
'
);
}
final
String
localizationsFile
=
fs
.
file
(
path
.
join
(
'lib'
,
'l10n'
,
defaultOutputFileString
),
).
readAsStringSync
();
expect
(
localizationsFile
,
contains
(
'''
import '
$
{
defaultOutputFileString
}
_en
.
dart
';
import '
$
{
defaultOutputFileString
}
_es
.
dart
';
import '
$
{
defaultOutputFileString
}
_zh
.
dart
';
'''
));
});
test
(
'imports are deferred when useDeferredImports are set'
,
()
{
fs
.
currentDirectory
.
childDirectory
(
'lib'
).
childDirectory
(
'l10n'
)..
createSync
(
recursive:
true
)
..
childFile
(
defaultTemplateArbFileName
).
writeAsStringSync
(
singleMessageArbFileString
);
final
LocalizationsGenerator
generator
=
LocalizationsGenerator
(
fs
);
try
{
generator
.
initialize
(
l10nDirectoryPath:
defaultArbPathString
,
templateArbFileName:
defaultTemplateArbFileName
,
outputFileString:
defaultOutputFileString
,
classNameString:
defaultClassNameString
,
useDeferredLoading:
true
,
);
generator
.
loadResources
();
generator
.
writeOutputFile
();
}
on
Exception
catch
(
e
)
{
fail
(
'Generating output files should not fail:
$e
'
);
}
final
String
localizationsFile
=
fs
.
file
(
path
.
join
(
'lib'
,
'l10n'
,
defaultOutputFileString
),
).
readAsStringSync
();
expect
(
localizationsFile
,
contains
(
'''
import '
$
{
defaultOutputFileString
}
_en
.
dart
' deferred as
${defaultOutputFileString}
_en;
'''
));
});
group
(
'DateTime tests'
,
()
{
group
(
'DateTime tests'
,
()
{
test
(
'throws an exception when improperly formatted date is passed in'
,
()
{
test
(
'throws an exception when improperly formatted date is passed in'
,
()
{
const
String
singleDateMessageArbFileString
=
'''
const
String
singleDateMessageArbFileString
=
'''
...
...
packages/flutter_tools/test/integration.shard/gen_l10n_test.dart
View file @
4451ffca
...
@@ -48,7 +48,7 @@ void main() {
...
@@ -48,7 +48,7 @@ void main() {
}
}
}
}
test
(
'generated l10n classes produce expected localized strings'
,
()
async
{
void
setUpAndRunGenL10n
({
List
<
String
>
args
})
{
// Get the intl packages before running gen_l10n.
// Get the intl packages before running gen_l10n.
final
String
flutterBin
=
globals
.
platform
.
isWindows
?
'flutter.bat'
:
'flutter'
;
final
String
flutterBin
=
globals
.
platform
.
isWindows
?
'flutter.bat'
:
'flutter'
;
final
String
flutterPath
=
globals
.
fs
.
path
.
join
(
getFlutterRoot
(),
'bin'
,
flutterBin
);
final
String
flutterPath
=
globals
.
fs
.
path
.
join
(
getFlutterRoot
(),
'bin'
,
flutterBin
);
...
@@ -58,8 +58,10 @@ void main() {
...
@@ -58,8 +58,10 @@ void main() {
final
String
genL10nPath
=
globals
.
fs
.
path
.
join
(
getFlutterRoot
(),
'dev'
,
'tools'
,
'localization'
,
'bin'
,
'gen_l10n.dart'
);
final
String
genL10nPath
=
globals
.
fs
.
path
.
join
(
getFlutterRoot
(),
'dev'
,
'tools'
,
'localization'
,
'bin'
,
'gen_l10n.dart'
);
final
String
dartBin
=
globals
.
platform
.
isWindows
?
'dart.exe'
:
'dart'
;
final
String
dartBin
=
globals
.
platform
.
isWindows
?
'dart.exe'
:
'dart'
;
final
String
dartPath
=
globals
.
fs
.
path
.
join
(
getFlutterRoot
(),
'bin'
,
'cache'
,
'dart-sdk'
,
'bin'
,
dartBin
);
final
String
dartPath
=
globals
.
fs
.
path
.
join
(
getFlutterRoot
(),
'bin'
,
'cache'
,
'dart-sdk'
,
'bin'
,
dartBin
);
runCommand
(<
String
>[
dartPath
,
genL10nPath
]);
runCommand
(<
String
>[
dartPath
,
genL10nPath
,
args
?.
join
(
' '
)]);
}
Future
<
StringBuffer
>
runApp
()
async
{
// Run the app defined in GenL10nProject.main and wait for it to
// Run the app defined in GenL10nProject.main and wait for it to
// send '#l10n END' to its stdout.
// send '#l10n END' to its stdout.
final
Completer
<
void
>
l10nEnd
=
Completer
<
void
>();
final
Completer
<
void
>
l10nEnd
=
Completer
<
void
>();
...
@@ -75,6 +77,10 @@ void main() {
...
@@ -75,6 +77,10 @@ void main() {
await
_flutter
.
run
();
await
_flutter
.
run
();
await
l10nEnd
.
future
;
await
l10nEnd
.
future
;
await
subscription
.
cancel
();
await
subscription
.
cancel
();
return
stdout
;
}
void
expectOutput
(
StringBuffer
stdout
)
{
expect
(
stdout
.
toString
(),
expect
(
stdout
.
toString
(),
'#l10n 0 (--- supportedLocales tests ---)
\n
'
'#l10n 0 (--- supportedLocales tests ---)
\n
'
'#l10n 1 (supportedLocales[0]: languageCode: en, countryCode: null, scriptCode: null)
\n
'
'#l10n 1 (supportedLocales[0]: languageCode: en, countryCode: null, scriptCode: null)
\n
'
...
@@ -133,5 +139,17 @@ void main() {
...
@@ -133,5 +139,17 @@ void main() {
'#l10n 54 (Flutter is "amazing", times 2!)
\n
'
'#l10n 54 (Flutter is "amazing", times 2!)
\n
'
'#l10n END
\n
'
'#l10n END
\n
'
);
);
}
test
(
'generated l10n classes produce expected localized strings'
,
()
async
{
setUpAndRunGenL10n
();
final
StringBuffer
stdout
=
await
runApp
();
expectOutput
(
stdout
);
});
test
(
'generated l10n classes produce expected localized strings with deferred loading'
,
()
async
{
setUpAndRunGenL10n
(
args:
<
String
>[
'--use-deferred-loading'
]);
final
StringBuffer
stdout
=
await
runApp
();
expectOutput
(
stdout
);
});
});
}
}
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