slang-i18n / slang

Type-safe i18n for Dart and Flutter
https://pub.dev/packages/slang
MIT License
459 stars 39 forks source link

Sort input files before generating translations #210

Closed poppingmoon closed 5 months ago

poppingmoon commented 5 months ago

Motivation For my project, I want to check if all generated files are up to date by running dart run slang and get diff on GitHub Actions. However, I found strings.g.dart is different between the one built on my Windows machine and the one built on GitHub Actions ubuntu-latest runner.

Here is a simple example. https://github.com/poppingmoon/slang_sort_example

In this example, we have two input files, lib/i18n/hello/hello.i18n.json and lib/i18n/world/world.i18n.json.

I ran dart run slang locally and got the following outputs.

> dart run slang
Generating translations...

Found slang.yaml!

 -> fileType: json
 -> baseLocale: en
 -> fallbackStrategy: none
 -> inputDirectory: lib/i18n
 -> inputFilePattern: .i18n.json
 -> outputDirectory: lib/i18n
 -> outputFileName: strings.g.dart
 -> outputFileFormat: singleFile
 -> localeHandling: true
 -> flutterIntegration: true
 -> namespaces: true
 -> translateVar: t
 -> enumName: AppLocale
 -> translationClassVisibility: private
 -> keyCase: null (no change)
 -> keyCase (for maps): null (no change)
 -> paramCase: null (no change)
 -> stringInterpolation: dart
 -> renderFlatMap: true
 -> translationOverrides: false
 -> renderTimestamp: true
 -> renderStatistics: true
 -> maps: []
 -> pluralization/auto: cardinal
 -> pluralization/default_parameter: n
 -> pluralization/cardinal: []
 -> pluralization/ordinal: []
 -> contexts: no custom contexts
 -> interfaces: no interfaces
 -> obfuscation: disabled
 -> imports: []

Scanning translations...

 (base) (hello) en -> lib/i18n/hello/hello.i18n.json
 (base) (world) en -> lib/i18n/world/world.i18n.json

Output: lib/i18n/strings.g.dart
Translations generated successfully. (0.128 seconds)

Next, I pushed this code and triggered GitHub Actions workflow. https://github.com/poppingmoon/slang_sort_example/actions/runs/8540342484/job/23397146622#step:5:45 This time, lib/i18n/world/world.i18n.json came before lib/i18n/hello/hello.i18n.json, so the ordering in strings.g.dart also differed.

It seems Directory.listSync returns files in an arbitrary order and this is causing the issue.

By sorting input files beforehand, files are always treated in the same order and output files should be reproducible.

This approach at least worked for my case. https://github.com/poppingmoon/slang/commit/0a7d041dab66e22b7349ef4a89e3156cbf203910 https://github.com/poppingmoon/slang_sort_example/actions/runs/8540394034/job/23397304286

Developer Experience How should devs use this new feature? Ex: There should be a new parameter called [...]

Tienisto commented 5 months ago

Thanks for noticing this. Could you open a PR?