Method 1 – starting with develop branch
This is an actual structure that most dev teams currently have, but mostly managed manually. Commiting/creating PRs/merging the English contents are still manual developer activities, but committing(delivering) translation files, notifying related stakeholders will be automated at the end, and these are all the tasks that the automation actually needs to handle.
However, once the translation files are delivered, in many cases of branching and merging, there will be chances that individual developers face translation file conflicts and try to resolve them.
This is an actual issue that we need to resolve with an automation stretegy.
In the early stage of i18n, this does not happen openly, but there will be a time that a significant number of developers ask around what they have to do with the translation file conflicts.
I have done a lot of brainstorming, and tried to implant various technical solutions that I thought were the best for dev teams’ architecture and branching strategy, and workflow.
Those are approaches that I have done:
- Creating string specific repo, then let core dev do remote checkout or use submodule.
- Branching stage branch, and use it only for translation files commits, then merging the files via PRs.
- Creating a middle layer build process, and recording what EN string comes from which feature branch, to avoid translation file conflict when developers merge back the translation file to the feature branch.
- Not using a static string file for contents, but using DB to store English and translated contents.
In the early stage of i18n, we propose to complete step 1 at first, then once we need a better solution, we propose and move on to step 2.
Method 2 – integrating external string repository:
The method 2 is to set up a separate string repository that only allows English content updates from developers and translation file commits from the translation team.
This solution isolates string resources from other code updates, reducing the effort needed to resolve conflicts. The method is aimed at reducing the need for developers to merge translation files like regular code files. However, an extra solution is still needed for the en-US file.
With the string specific external repository solution, there can be few additional required updates:
- Developers have to manage common code commits, and EN content updates separately when they commit new feature updates.
- dev-A completed a feature development with EN contents updates. dev-A has to commit the EN contents to external repo for translation request, and dev-A has to commit other common code updates to the develop branch.
- Need a process where developers can consolidate all English contents in en-US files in an external repository, and make this repo as the source of the most up-to-date en-US contents.
- dev-A and dev-B will work on different features, then at some point they have to commit their EN contents to external repo for translation.
- dev-C and dev-D will work on new features, then they need to cut new branches, and these branches have to have recent English contents.
- Stage branch build(for QA), and production branch build(for release), those builds need to have en-US & translation files from this external string repository.
Why are conflicts occurring on the English resource files and the translation files?
Even if the dev team integrated the external string repository via git submodule, they will still have file conflicts especially on English resource files.
When conflicts occur in English resource files, it is usually because one or more developers have made different modifications to the same en/*.json file. This is a natural cause of conflict and requires resolution, but it is not a significant issue for a small size of companies.
However, for products such as social games that release large amounts of English content at once with at least one-week intervals, and for products with more than 15 developers, a special solution is needed for conflicts in English files.
On day-1, A developer started his/her work by creating a feature branch from develop branch using “
$ git checkout -b“.
On day-2, i18n team delivered translation updates to “public/es-ES/login.json” (modifying translations from the previous “es-ES/login.json”).
On day-3, when the developer committed his/her feature branch code files, any modification made to “es-ES/login.json” in their branch resulted in conflicts.
This can happen in any way, even unintentionally due to lint. In this case, we can simply add “locales/es-ES” to the ignore list in the lint configuration according to the rule of “should not modify the translation file”.
However, developers may not be aware of the reason why they need to ignore “locales/xx-YY” until they receive education on internationalization.
What does it mean to consolidate all English content updates from individual feature branches?
The string repository contains en-US/*.json and translated files xx-YY/*.json (such as es-ES/login.json).
In the current state, each developer has the same source for the English content (en-US/.json), but as the development progresses, they each have their own updates in en-US/.json.
The task of consolidating each developer’s updates into the en-US/*.json file in the string repository is what is meant here.
Simply put, the en-US/*.json files in the development branches where developers work act as a middle layer, holding the individual English contents updates. The final English file that is usable for the product is the en-US/*.json file in the string repository.
Now, the question arises of how the middle layer’s en-US/*.json file is synced with the en-US/*.json file in the string repository and when that sync should happen. This can be different depending on the development team’s architecture (via git action, common branching and merging, CI/CD, etc.), but there are some unchanging truths:
- the en-US/*.json file in the string repository should store all the English content at a certain time (such as when creating a translation task or releasing the app).
- it should allow other branches in different repositories to subscribe (for example, via submodule) to the latest English content when needed for certain purposes (such as creating a new development branch or building the release/QA app).
How does collaboration between developers and the external string repository look?
Continuing from the discussion on en-US/*.json as a middle layer concept versus en-US/*.json as the final content subscription, it goes as follows:
Developer A needs the en-US/*.json as a subscription when creating a feature branch because he/she needs to develop a feature on top of the latest content.
In this case, whether it is done manually or through a script, the developer needs to link their personal feature branch to the string repository (which serves as a subscription for en-US/*.json). If Git submodule is already set up, once the developer creates a feature branch and downloads the branch code locally, they can use “
$git submodule init;git submodule update” to fetch the latest string updates to their local machine.
Developer A has created a feature branch for updating code and including new English content updates in locales/en/*.json. However, it seems that a separate content update branch needs to be created in the string repository that is linked as a submodule. To do this, Developer A navigates to the public directory and creates a new development branch for the string repository with “
$cd public; git checkout -b <contentsbranch>“.
Check out the <contentsbranch> locally using the command “
$git checkout <contentsbranch>“
Other developers (Developer B) also create feature branches in the same way and work on their own feature development.
Developer A now completes feature development and prepares to commit the code. First, they execute “
$ git pull origin develop” to fetch the latest code in the develop branch to their local repository. Then, they stage and commit only the code to the develop branch using “
$ git add/commit“.
Next, Developer A prepares a commit for the string repository for the consolidation of locales/en-US/*.json.
Merge other developers’ English content updates into the local <contentsbranch> – “
$ git submodule update --remote --merge“
In this case, there may be a conflict between the changes made by Developer A and the updates made by other developers in the en-US/*.json files.
Resolve the conflict.
The content update is committed to the remote <contentsbranch> using
Pushes the submodule updates using “
$git push --recurse-submodules=on-demand“, and then pushes the feat branch.