Skip to content

WIP: Console translation - #1564

Closed
Meldiron wants to merge 26 commits into
0.10.xfrom
feat-console-translation
Closed

Meldiron wants to merge 26 commits into
0.10.xfrom
feat-console-translation

Conversation

@Meldiron

@Meldiron Meldiron commented Sep 2, 2021 •

Copy link
Copy Markdown
Contributor

What does this PR do?

This PR makes it possible to translate the whole Appwrite console into any language by taking texts from code into json file.

Test Plan

To run test, do docker-compose exec appwrite test /usr/src/code/tests/e2e/General/LocaleMissingTest.php

I prepared a test that checks for ->getText( with keys that are not presented in en.json. This check ignores continents and countries because these are used with dynamic keys.

For tests to work properly, we can' use variable names as a key.

If someone decides to write text directly into code without using getText, this test won't catch that.

Tests also won't spot when you define a translation in en.json and don't use it anywhere in the code (most likely wrong CopyPaste, happened to me multiple times).

Additionally, tests will log 20 most used values in en.json. This helps you spot duplicates when refactoring a bigger part of the UI (for example, I used 18 keys for the value "Cancel").

Connections with other branches

  • Database refactoring needs to be merged due to database translation
  • Deprecate tasks. They are not translated
  • Realtime needs to be merged due to home translation
  • MagicURL might need to be merged due to users translation

Issues to discuss

This is a draft PR to start discussing issues about localization

1. Dynamic values

Problem:

English: The project has 3 collections taking 12 MB space and includes 512k files.

Solution:

English: The project has { collectionsAmount } collections taking { spaceUsage } space and includes { documentsAmount } files.

In code you would do something like:

<?php echo $locale->getText("my-key", [
  'collectionsAmount': 3,
  'spaceUsage': '12 MB',
  'documentsAmount': '512k'
]); ?>

2. Pluralization

Problem:

English: Meldiron ate 1 apple / Meldiron ate 2+ apples
Slovak: Meldiron zjedol 1 jablko / Meldiron zjedol 2/3/4 jablká / Meldiron zjedol 5+ jabĺk

Solution:

English: Meldiron ate { applesAmount } { applesAmount, PLURAL, =1 {apple} other {apples} }
Slovak: Meldiron zjedol { applesAmount } { applesAmount, PLURAL, =1 {jablko} few {jablká} other {jabĺk} }

Keywords:

  • =X exact number
  • one alternative to =1
  • few 2, 3 or 4
  • other anything else

More info: https://www.npmjs.com/package/messageformat

In code you would do something like:

<?php echo $locale->getText("my-key", [
  'applesAmount': 4 // Used by both dynamic values and pluralization
]); ?>

3. Gender

Problem:

English: Meldiron is ready / Sara is ready
Slovak: Meldiron je pripravený / Sara je *pripravená

(verbs change depending on gender)

We ignore this one for now because we don't store gender

4. Nested translations

Problem:

<p>By signing up, you agree to the <a data-ls-attrs="href={{env.HOME}}/policy/terms" tabindex="-1" target="_blank" rel="noopener">Terms and Conditions</a> and <a data-ls-attrs="href={{env.HOME}}/policy/privacy" target="_blank" tabindex="-1" rel="noopener">Privacy Policy</a></p>

How we would translate it:

   "home.auth.signup.agree-terms-chunk1": "By signing up, you agree to the",
    "home.auth.signup.agree-terms-chunk2": "Terms and Conditions",
    "home.auth.signup.agree-terms-chunk3": "and",
    "home.auth.signup.agree-terms-chunk4": "Privacy Policy",

Solution with dynamic values would not help... We would still have nested translations Terms and Conditions and Privacy Policy inside a placeholder. We would go to 3 chunks from 4, but still not a solution.

Solution:

Mark nested placeholders and write a logic to apply it.

How Localazy solves it:

   "home.auth.signup.agree-terms": "By signing up, you agree to the {$START_A} Terms and Conditions {$END_A} and {$START_A} Privacy Policy {$END_A}",

_A represents <a> tag so developers can find it easier in the bigger block. This solution requires some library that would extract and inject the translation without breaking the HTML.. Not really sure how Localazy does it.

How I would solve it:

   "home.auth.signup.agree-terms": "By signing up, you agree to the {termsTag, NESTED, 'Terms and Conditions'} and {privacyTag, NESTED, 'Privacy Policy'}",

and in code we could have something like:

<p> <?php echo $locale->getText('my-key', [
  'termsTag': '<a data-ls-attrs="href={{env.HOME}}/policy/terms" tabindex="-1" target="_blank" rel="noopener"> { $text } </a>',
  'privacyTag': '<a data-ls-attrs="href={{env.HOME}}/policy/privacy" target="_blank" tabindex="-1" rel="noopener"> { $text } </a>'
]); ?>

({ $text } would be a reserved word; we follow the same pattern as pluralization solution)

Author comments

  • Don't forget about database translation after refactoring

@Meldiron

Meldiron commented Sep 8, 2021 •

Copy link
Copy Markdown
Contributor Author

After working on the translations I found specific examples of these problems in the code. I think that Pluralization is still a needed feature.

Dynamic values + Pluralization

Not as problematic as I thought it would be. I don't think we will need this on more than 10 places in the whole appwrite console. Problem is that if a contributor sees functions found he does not really understand that there will be a number in front... Also, some languages might need to put the number in between words or at the end, which would be a problem.

  • 12 functions found
  • 55 files found

CleanShot 2021-09-08 at 08 24 07

Nested translations

So far, I have only seen this 3 or 4 times in total. I would even say this is less important than pluralization. This can be easily solved with the system of chunks we use currently:

    "home.auth.join.agree-terms-chunk1": "By accepting the invitation, you agree to the",
    "home.auth.join.agree-terms-chunk2": "Terms and Conditions",
    "home.auth.join.agree-terms-chunk3": "and",
    "home.auth.join.agree-terms-chunk4": "Privacy Policy",

We can add one note into the translation tutorial on how these chunks work and we should be good.

CleanShot 2021-09-08 at 08 23 39

@Meldiron

Meldiron commented Sep 8, 2021

Copy link
Copy Markdown
Contributor Author

CleanShot 2021-09-08 at 11 49 13

Do we translate these? 🤔 Sure, it would be nice to see everything in my language but these are keywords from the API server and it might get confusing.

@Meldiron

Copy link
Copy Markdown
Contributor Author

Dynamic values

Implemented 🤩

Pluralization

Ignored, for now, will be added in future.. Some time... Not this PR.

Nested translations

Ignored, there are only +-5 use-cases, we will stick to chunk system.

@Meldiron Meldiron mentioned this pull request Sep 18, 2021
3 tasks
@TorstenDittmann
TorstenDittmann deleted the feat-console-translation branch September 10, 2023 15:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants