yalo 3.0.0 yalo: ^3.0.0 copied to clipboard
Yalo (Yaml localizations) - is a package, which give you a simplest way to get localizations from yaml files
Yaml localizations (and assets codegen) #
[yalo:loc] How to use #
1. Localization files #
After installing this package you can use .yaml
files with localization content. You can place these files in this order
assets/**/language_code/intl.yaml
assets/**/language_code.intl.yaml
assets/**/language_code_intl.yaml
Where language_code
is a ua
/ en
/ de
, etc. Like in example
assets/localizations/ua/intl.yaml
assets/en/intl.yaml
assets/content/de_intl.yaml
assets/zh.intl.yaml
2. Describe path to the assets folder #
Of course, you must also specify the path to the assets folder in pubspec.yaml
# pubspec.yaml
# ...
flutter:
# ...
assets:
- assets/
# ...
3. Run the command #
When you created all localization files, then run command
flutter pub run yalo:loc
4. Add generated localization dependency to your project #
This command will generate a .yalo_locale
folder in your project's root directory. Then, add this package as a dependency to your pubspec.yaml
file
# ...
dependencies:
# ...
yalo_locale:
path: ./.yalo_locale
# ...
# ...
5. Use and enjoy #
Now you can use generated localization delegate in your app! Yalo provides you to use a simple variable localizationsDelegates
, which you can use in your MaterialApp
or CupertinoApp
. And also,
you can use generated variable supportedLocales
, which contains all your locales
import 'package:yalo_locale/lib.dart';
class PresidentsApp extends StatelessWidget {
const PresidentsApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
localizationsDelegates: localizationsDelegates,
supportedLocales: supportedLocales,
locale: DevicePreview.locale(context),
onGenerateTitle: (BuildContext context) =>
Messages
.of(context)
.app
.title,
theme: ThemeData(
primarySwatch: Colors.blue,
),
useInheritedMediaQuery: true,
builder: DevicePreview.appBuilder,
home: const MyHomePage(),
);
}
}
To get access to current localization content, use Messages.of(context)
. This method will return your current's locale content
Widget build(BuildContext context) {
final LocalizationMessages loc = Messages.of(context);
return Scaffold(
appBar: AppBar(
title: Text(loc.app.description),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Padding(
padding: const EdgeInsets.only(bottom: 20),
child: Text(
loc.books(user: loc.presidents.getContent('p$_counter'), howMany: _counter),
textAlign: TextAlign.center,
),
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: loc.tooltips.increment,
child: const Icon(Icons.add),
),
);
}
Also, you can use a static fields of Messages
with localized content too. For every language will be generated a static field. For example:
class Messages {
static LocalizationMessages of(BuildContext context) => Localizations.of(context, LocalizationMessages);
static LocalizationMessages get de => LocalizationDelegate()._languageMap['de']!;
static LocalizationMessages get en => LocalizationDelegate()._languageMap['en']!;
}
Localization files format #
1. Simple message #
# The simplest possible message type [SimpleMessage]
cancel: Cancel
/// Description: ""
/// Example: "Cancel"
@override
final String cancel = Intl.message(
'''Cancel''',
name: 'cancel',
desc: '',
);
2. Simple message with description #
# Simple message type with description [SimpleMessage]
save:
value: Save
desc: Saving something
/// Description: "Saving something"
/// Example: "Save"
@override
final String save = Intl.message(
'''Save''',
name: 'save',
desc: 'Saving something',
);
3. Simple message with substitution #
# [SimpleMessage] with additional substitution params
greetings: Hello ${userName}! We are glad to see you at our ${hotelName} hotel!
/// Description: ""
/// Example: "Hello $userName! We are glad to see you at our $hotelName hotel!"
@override
String greetings({
required String userName,
required String hotelName,
}) =>
Intl.message(
'''Hello $userName! We are glad to see you at our $hotelName hotel!''',
name: 'greetings',
desc: '',
);
4. Simple message with description and substitution #
# [SimpleMessage] with description and substitution params
weather:
value: It's ${temperature} degrees outside today!
desc: "Title on the main weather screen (see here: https://www.figma.com/community/file/974352831498882628)"
/// Description: "Title on the main weather screen (see here: https://www.figma.com/community/file/974352831498882628)"
/// Example: "It's $temperature degrees outside today!"
@override
String weather({
required String temperature,
}) =>
Intl.message(
'''It's $temperature degrees outside today!''',
name: 'weather',
desc: 'Title on the main weather screen (see here: https://www.figma.com/community/file/974352831498882628)',
);
5. Plural message #
For additional info about plural rules go here
# [PluralMessage]
book:
# Required parameter of plural message
zero: books
# Required parameter of plural message
one: book
# Optional parameter of plural message
two: books
# Optional parameter of plural message
few: books
# Optional parameter of plural message
many: books
# Required parameter of plural message
other: books
# Optional parameter of plural message
desc: Uses for description of books count
/// Description: "Uses for description of books count"
/// Example: "zero: books, one: book, two: books, few: books, many: books, other: books"
@override
String book(int howMany, {int? precision}) =>
Intl.plural(
howMany,
name: '''book''',
zero: '''books''',
one: '''book''',
two: '''books''',
few: '''books''',
many: '''books''',
other: '''books''',
desc: '''Uses for description of books count''',
precision: precision,
);
6. Plural message with using of quantity in the text #
# [PluralMessage]
people:
zero: I saw no people there
one: I saw only one man there
two: I saw two people there
# Message with substitution of quantity of something
few: I saw ${howMany} people there
many: I saw ${howMany} or more people there
other: I think, I saw ${howMany} people there
desc: An example with numeric substitution in plural strings
/// Description: "An example with numeric substitution in plural strings"
/// Example: "zero: I saw no people there, one: I saw only one man there, two: I saw two people there, few: I saw $howMany people there, many: I saw $howMany or more people there, other: I think, I saw $howMany people there"
@override
String people(int howMany, {int? precision}) =>
Intl.plural(
howMany,
name: '''people''',
zero: '''I saw no people there''',
one: '''I saw only one man there''',
two: '''I saw two people there''',
few: '''I saw $howMany people there''',
many: '''I saw $howMany or more people there''',
other: '''I think, I saw $howMany people there''',
desc: '''An example with numeric substitution in plural strings''',
precision: precision,
);
7. Plural message with extra substitution params #
# [PluralMessage] with additional substitution params and quantity substitution param
shop:
zero: There are no any ${shopName} shops
one: There are exactly one ${shopName} shop
two: There are two ${shopName} shops
few: There are ${howMany} ${shopName} shops and we have plans to open additional at the ${city}!
many: There are ${howMany} shops. Sorry, I didn't remember that shop name.
other: Well, I tired to count these shops. I can say that there are only ${howMany} shops!
/// Description: ""
/// Example: "zero: There are no any $shopName shops, one: There are exactly one $shopName shop, two: There are two $shopName shops, few: There are $howMany $shopName shops and we have plans to open additional at the $city!, many: There are $howMany shops. Sorry, I didn't remember that shop name., other: Well, I tired to count these shops. I can say that there are only $howMany shops!"
@override
String shop({
required String shopName,
required int howMany,
required String city,
int? precision,
}) =>
Intl.plural(
howMany,
name: '''shop''',
zero: '''There are no any $shopName shops''',
one: '''There are exactly one $shopName shop''',
two: '''There are two $shopName shops''',
few: '''There are $howMany $shopName shops and we have plans to open additional at the $city!''',
many: '''There are $howMany shops. Sorry, I didn't remember that shop name.''',
other: '''Well, I tired to count these shops. I can say that there are only $howMany shops!''',
desc: '''''',
precision: precision,
);
8. Namespaced content #
# Namespace of group of messages [MessagesNamespace]
namespacedZone:
# [SimpleMessage]
title: Title of Namespaced zone
# [SimpleMessage]
description: Description of Namespaced zone
# [MessagesNamespace]
checkout:
# [SimpleMessage]
title: Checkout for additional page
# [MessagesNamespace]
innerNamespacedZone:
# [SimpleMessage]
title: Deeper title of Inner namespaced zone with name ${name}
# [SimpleMessage]
description: Deeper description of Inner namespaced zone
# [PluralMessage]
book:
# Required parameter of plural message
zero: books
# Required parameter of plural message
one: book
# Optional parameter of plural message
two: books
# Optional parameter of plural message
few: books
# Optional parameter of plural message
many: books
# Required parameter of plural message
other: books
# Optional parameter of plural message
desc: Uses for description of books count
# ...
# [MessagesNamespace]
app:
# [SimpleMessage]
title: Yalo app
# [SimpleMessage]
description: This app will show you how to use yalo package
/// This is an example of how namespaces works
final String bookTitle = Messages
.of(context)
.namespacedZone
.innerNamespacedZone
.book(booksQuantity);
final String checkoutTitle = Messages
.of(context)
.namespacedZone
.checkout
.title;
// ...
final String appTitle = Messages
.of(context)
.app
.title;
9. Link to another language file #
It may happen that some block of content will be the same in all languages. In such a case, you can only define this content in one language and link to it in other languages. For example like this:
# en.intl.yaml
presidents:
p1: George Washington
p2: John Adams
p3: Thomas Jefferson
p4: James Madison
# ...
# de.intl.yaml
presidents: ~en.presidents
An important note about this feature: at the moment, only first-level (root) elements can be referenced this way.
Dynamic access #
In addition to accessing content in a class style, you can also access it dynamically using the T getContent<T>(String key)
method of any namespace-class or root LocalizationMessages
entity. Thus,
you can both move along the chain of class-namespaces, and simply get something dynamically. See here:
mainView:
firstTab:
secondStory:
example:
title: This is a title
description: This is a description
---
presidents:
p1: George Washington
p2: John Adams
p3: Thomas Jefferson
p4: James Madison
# ...
final String title = loc
.getContent<MainView>('mainView')
.getContent<MainViewFirstTab>('firstTab')
.getContent<FirstTabSecondStory>('secondStory')
.getContent<SecondStoryExample>('example')
.getContent('title');
final Widget widget = Padding(
padding: const EdgeInsets.only(bottom: 20),
child: Text(
loc.books(user: loc.presidents.getContent('p$_counter'), howMany: _counter),
textAlign: TextAlign.center,
),
);
Examples #
You can see additional examples of generated code, its usage, as well as localization source files in GitHub.
Assets #
To generate code with your assets paths, you should run this command:
flutter pub run yalo:asset
This command will generate a .yalo_assets
folder in your project's root. Also, as written above, you must add this folder as a dependency of your project:
# ...
dependencies:
# ...
yalo_assets:
path: ./.yalo_assets
# ...
# ...
After that, you can use Assets
class with static and usual fields in your project:
import 'package:yalo_assets/lib.dart';
// MyHomePageState.dart
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
_buildText('Assets example: ${Assets.rigDemoS}'), // <-- this static field contains "assets/rive/Rig Demo.flr2d" string
_buildText('Assets example: ${Assets().rigDemo}'), // <-- this field contains "assets/rive/Rig Demo.flr2d" string
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}