Code Monkey home page Code Monkey logo

godot-fluent-translation's People

Contributors

redmser avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

godot-fluent-translation's Issues

Investigate binary AST storage

Games could store the AST in a binary serialization, so that parsing of .ftl files is not required at runtime. This could be done in a conversion step by an editor import plugin (related to #1). Formats like .png get imported and remapped to a .ctex file, this would be a similar approach.

This saves disk space, can combine multiple files into one, and could minify the data by e.g. removing all comment tokens.

See projectfluent/fluent-rs#352 for upstream support, although unlikely to happen.

Since fluent_bundle::FluentResource only takes a String as input, might need to use a compatible trait and/or insert entries by hand.

Avoid "experimental-threads" feature

Need "experimental-threads" feature since Godot calls get_message threaded, or at least gd-rust seems to think so.

Might be an upstream issue (there are other similar issues on the repo, but not exactly the same).

Create fallback build that works without forked Godot

  • Feature flag that decides whether your Godot build is forked or master/stable.
  • Translate args: instead of tr(msg, args, context) it could be something like tr(var_to_str(args) + msg, context)
    • So code would pass an empty args dict by default, but if it sees that the message starts with { it would parse the string to a Dictionary variant and use that for args.
    • Could create a helper function fluent_args(msg, args) which creates a string formatted like this.
  • #19

Allow registering custom functions

FluentBundle::add_function allows registering a custom function to call in FTL.
This could be exposed to GDScript to allow registering custom callables.

Platform Compatibility

See BUILDING.md for an up-to-date list of which platforms are supported.

Compiling

First of all, it'll help to know which platforms compile out-of-the-box and which ones need extra attention to get working.

I'd like to set up the CI/CD for all supported platforms, to make this easier to keep track of. While my fork builds compile on all major platforms, the CI/CD of this repo does not.

Testing

Even if a platform compiles, it would be nice to test if both the forked executable runs, and if the extension works as expected.

Replace complex Project Settings with a plug-in API

Many project settings are too complex for their own good, using RegEx or Dictionary for very complex lookups and string manipulation.

Instead it would be good to have a plug-in API that allows the user to implement virtual methods like func _compute_locale(path: String) -> String which could in the end just do a RegEx lookup, but also anything else.

Not sure about the registration mechanism, since it would need to be available as soon as ResourceLoader is ready (during project startup). Maybe refer to plug-in classes by path or by class_name in ProjectSettings?

May depend on godot-rust/gdext#426

Remove comments from export

Simpler implementation of #6

Comments from exported games FTL files could be stripped, to avoid leaking information and to slightly reduce file size.

Support older Godot versions

As outlined in BUILDING.md, there are some APIs which only exist in v4.3 dev 6, locking us to this version.

Would be nice to allow going back to v4.2 or even v4.1 (anything earlier is impossible due to binary incompatibility).

Open Question: How do we run backwards compatibility methods, and choose to take that code path based on engine version? Ideally, we should make use of e.g. AutoTranslateMode/resize methods if they exist, but fallback to old APIs otherwise. So this shouldn't be cfg macros, but rather some form of dynamic calls and version check.

Will likely only affect the Default builds / AssetLib, since I'll release Forked versions only for latest Godot.
But of course older Forked builds can be self-compiled as well then.

Upstream API changes to Godot

Applied in fork

Not yet implemented

  • Backwards compatibility methods for the "args" parameter.
  • ScriptEditor::open_file only checks for Script and JSON resources to determine what it can open
    • TODO: should check if this is also what determines if double-clicking a file in FileSystem dock opens the script editor

FTL generation

Could take the PotGenerator class, create an abstract base class / plugin registration system, then allow generating FTL files the same way. Obviously needs larger upstream changes.

While POT uses English messages as translation keys, FTL has separate keys. So unlike POT, you'll want to enter translation keys into your UI, and have those get extracted like key = UNTRANSLATED. Not sure how this works with ETR/ETRN translations though (I don't think FTL supports spaces in translation keys, so those might need to be converted to a "compatible" format)...

Alternative approach would be a custom EditorPlugin that adds some kind of UI. This provides more flexibility:

  • It could be interesting to allow multiple FTL files split up in some way, e.g. by folder or by file.
  • Existing files can be merged so that existing changes don't get lost - new keys are appended.
  • Similar "translation extraction plugin" class that the user can write to decide how certain files should fill a FTL:
    • Would also support extracting attributes and terms.
    • Could let the user choose whether they want the messages themselves to be translation keys (with some "convert illegal characters to underscores/dashes" logic), or define custom translation keys.
    • Could generate boilerplate for plural selectors?

First draft for how to configure this (no UI, just plaintext multiline):

locales = ["en", "de", ...]

[source files regex]
[generated ftl files]
...
  • Each file in the project is iterated and matched against the specified source regex.
    • Capture groups can be re-used later.
  • If a file matches, loop over all configured locales.
    • For each locale, fill out the ftl file string's placeholders:
      • {$locale} is replaced with the current locale
      • {$n} is replaced with the n-th matched capture group
    • If the ftl file does not exist, create it.
    • If the ftl file already exists, merge it with the existing contents.
      • Create new messages.
      • Leave existing messages untouched.
      • Mark no longer existing messages with a comment for inspection.
  • Repeat this process for all source > ftl lines.

Example syntax:

ui/(.+)\.tscn
i18n/{$1}.{$locale}.ftl

Investigate usage of Time/TextServer singletons

Fluent does some time/date/number formatting using its own functions.

But Godot also has similar functions, so we should use those instead to save on file size and make formatting consistent with the engine.

Have not investigated the differences and if it's even worth doing this...

(Default Version) Automated loading of Translations on startup

Forked version allows Project Settings to contain .ftl files like normal. This does not work for default builds, see #11.

There are code workarounds for loading translations, so it's probably fine. Maybe could introduce a helper function which recursively finds all *.ftl files in the project and loads them? Could optionally filter by locale, or path glob.

(This would also make .ftl files show in the translation picker dialog - no need to do anything else)

FTL Generator: API for construction

  • Create static method to make a new FTL Generator based on Project Settings.
  • Create instance methods to add/remove/get locales and patterns.

FTL Generator: Integrate into Godot Editor

Instead of user writing custom tool script, find a convenient place to expose the generator as a button out-of-the-box.

Ideas

  • Next to POT Generator tab, but unsure if this area is extensible.
  • Somewhere in the menus.
  • Custom button in Project Settings -> Fluent, but unsure if that is possible (inspector plugin maybe?).

Other ideas are welcome.

Continuous Deployment

I'm assuming that configs for this already exist, so implementing this should just be a matter of research and fine-tuning the configuration for this project.

CI

  • Compile and run linter.
    • Probably fine to only cancel on errors, but ignore linter stuff. My Rust isn't pretty :D
  • On master branch and for pull requests.
  • Publish custom tags + releases on my Godot fork, and pull forked engine builds from there instead.
    • The download instructions + gdextension releases page would simply link to the releases page on there.

CD

  • Build artifacts from CI.
    • Needs a separate workflow to create all needed files for a release:
      • Windows [Default] debug+release
      • Linux [Default] debug+release
      • Windows [Forked] debug+release
      • Linux [Forked] debug+release

Class documentation

Depends on godot-rust/gdext#178 or a direct call to editor_help_load_xml_from_utf8_chars (not exposed by godot-rust).

Will only really be helpful once the API has more members - not sure if ProjectSettings can already be documented for GDExtensions.

CI: Use latest Godot version instead of a specific tag

For [Default]โ€‹ builds, we currently hard-code a specific tag to download. We should switch to latest: true and preRelease: true, but then following commands won't know the executable file name anymore.

Needs to use downloaded_files output.

We have to find out what the extracted executable file name is. Can this be inferred from the zip file name? Or do we need to look through the variable to find a matching executable?

Create integration tests

  • Both the forked and default sample projects should contain a simple integration test. Load translations in different ways, translate a message with args, run the generator, ...
  • Run this test either using a framework like Gut or via godot --headless --script test.gd
  • Insert this into the CI pipeline, after the respective builds completed. (So after Windows Forked, run forked test. After Linux Default, run default test.)

Resource importer for FTL files + Better API

Check the CSV importer for reference on how to implement this.

  • ResourceFormatLoader: works in game and in editor. Could load .ftl files at runtime.
  • EditorImportPlugin: only works in editor.
    • Variant 1: Saves .translation files like CSV, which would lose FTL data (only keeping messages with empty args) -> this approach does not make sense.
    • Variant 2: Store AST for quicker reconstruction of FTL data (see #6).

Ideally it should be possible to have multiple FTL files for one language, which can be merged. But neither a requirement, nor am I sure how Godot currently handles multiple Translations for the same locale. Would need to check for conflicting entries as well, or maybe adding multiple bundle files to the same Translation resource...

API should be improved e.g. by removing redundant language ID.

Edit FTL files directly in Godot

  • Make .FTL files editable in script editor (see #11 under "not yet implemented")
  • Add simple syntax highlighting - see how the vscode extension highlights stuff, which textmate rules it has

Better error handling

The error handling could be a bit more accurate. See some of the TODOs in the Rust code.

Only add it where it makes sense and where it doesn't add too much code complexity.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.