Skip to content

fix(make_game): a launcher's build keeps the folder's language, and a first one takes the system's (#2184) - #2284

Merged
hckrman101 merged 2 commits into
NotRexed:mainfrom
jarynclouatre:fix/launcher-build-language
Nov 11, 2026
Merged

hckrman101 merged 2 commits into
NotRexed:mainfrom
jarynclouatre:fix/launcher-build-language

Conversation

@jarynclouatre

@jarynclouatre jarynclouatre commented Nov 11, 2026 •

Copy link
Copy Markdown
Contributor

A game built through RecompLauncher is always in English, and a language the player set in language.txt goes back to English the next time the launcher builds the folder (#2184).

Why

The launcher builds with --cli --prepare --game <copy> (recomplauncher.json): no window, and no --language. make_game.py took en-US for that and wrote it to language.txt at the end of every build. Only --update read the folder's own language first.

So the one way a launcher's player has to change the language, the code in language.txt (the file says so itself, and the readme's "wrong language" row), lasted until the next build. Anything else that writes the player's choice to that file is undone the same way; the "Game language" row of #1864 would be.

The change

With no --language, a build now takes, in this order:

  1. the language the folder has: the build before, or the player's own change to language.txt;
  2. with --prepare and no folder yet: the game language closest to the system's (on Linux LANGUAGE's first entry unless the locale is C, else LC_ALL, LC_MESSAGES, LANG, as gettext reads them; on Windows the display language, the first of GetUserPreferredUILanguages, as the builder's CurrentUICulture), by the rule the Windows builder's window uses for its first choice (the exact one, then the family; es-MX is Spanish (Latin America), zh-TW Chinese (Traditional));
  3. en-US, as before.

A --language given is still the one built, so both builder windows, which always pass theirs, are unchanged. --update keeps the folder's as before. A plain command line build without --language is still English into a new folder; into a folder built before it now keeps that folder's language rather than turning it English.

Tested

  • Linux: python -I -B tests/test_make_game_prepare.py: 17 pass, 8 of them new. One runs main itself up to its first step with --prepare over a folder whose language.txt says ru: on main it fails with 'en-US' != 'ru', here it is ru. The others cover the order above, the system names (de_DE.UTF-8, pt_PT, es_MX, zh_TW, zh-Hant-HK, C, ...) and which of the three variables is read.
  • Linux: python -I -B tests/run_all.py: nothing new fails.
  • Windows 11 (Python 3.13.7): python -I -B tests\test_make_game_prepare.py, 16 pass and the Linux environment one skips. On that PC the display language is en-US and the regional format en-CA; system_language() reads en-US, where GetUserDefaultLocaleName (the rule before review) read en-CA.

Not tested: a whole build through RecompLauncher (no launcher here), and a Windows locale the game has a language for.

Part of #2184

… first one takes the system's (NotRexed#2184)

RecompLauncher builds with --cli --prepare --game, which has no window and
passes no --language: every such build wrote en-US to language.txt. A
player who had put their language in that file, as the file and the readme
say to, got English back the next time the launcher built the folder, and
a first build was English whatever the system's language.

A build with no --language now takes the language the folder has (the
build before, or the player's own change to language.txt); with --prepare
and no folder yet, the game language closest to the system's, picked as
the Windows builder's window picks its first one; else en-US as before. A
--language given is still the one built, so the builders' windows, which
always pass theirs, build as they did. --update keeps the folder's, as
before.
@Felitendo

Copy link
Copy Markdown

yes that would be awesome if we could get this merged

@Joey-Magnus Joey-Magnus left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good fix, and the order is right: an explicit --language wins, an update keeps the folder's language, then the folder's own language, then the system's (only with --prepare), then en-US. Moving a.language to after out is resolved means the plain command-line build and the update path now share one rule. Both builder windows always pass --language, and their update paths rely on the folder's language. I checked MainWindow.xaml.cs:752, window.py:1342 and builder/linux/hookshot_builder.py:1043. tests/test_make_game_prepare.py and the other make_game checks pass here, the branch merges cleanly with main, and the appimage failure is a Launchpad timeout, not this PR.

  • should fix nx2/make_game.py:1126 reads GetUserDefaultLocaleName. That returns the user's regional-format locale (Settings → Region → Format), not the display language. The Windows builder picks its first language from CultureInfo.CurrentUICulture (builder/HookshotBuilder/Strings.cs:165), which is the UI language. The two often differ. Someone with English Windows and German or Polish regional formats would get a German or Polish game from the launcher, and the opposite also happens. That breaks the "by the rule the Windows builder's window uses" claim. Reading the UI language instead would match the builder, for example:

    k32 = ctypes.windll.kernel32
    buf = ctypes.create_unicode_buffer(85)
    name = buf.value if k32.LCIDToLocaleName(k32.GetUserDefaultUILanguage(), buf, 85, 0) else ""

    (GetUserPreferredUILanguages is the closer match to .NET if you want the first entry of the list.)

  • minor On Linux, gettext puts LANGUAGE ahead of LC_ALL/LC_MESSAGES/LANG for message catalogs. Some desktops, including GNOME's language setting, set it, e.g. LANGUAGE=de:en. If you want to match what the desktop shows, check its first entry before the others (and still ignore it when the locale is C, as gettext does). Fine to leave out if you'd rather stay with the three.

  • minor CONTRIBUTING's build table (line 151) and the readme (lines 512–513) still show --language en-US in every example, which is fine, but nothing documents the new behaviour without --language. One sentence in the readme near line 215 ("The game is in the wrong language") would help: rebuilding now keeps the language set in language.txt.

…nd LANGUAGE's first on Linux

GetUserDefaultLocaleName is the regional format, often not the display language the Windows builder's
window follows (CurrentUICulture): read GetUserPreferredUILanguages' first, else GetUserDefaultUILanguage.
On Linux, LANGUAGE's first entry comes first unless the locale is C, as gettext reads it. The readme's
wrong-language line says an update keeps language.txt's choice.

@Joey-Magnus Joey-Magnus left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The precedence (--language, the folder's language on update, the system's with --prepare, then en-US) is right, and all 17 tests pass.

The open point is still open: nx2/make_game.py:1126 uses GetUserDefaultLocaleName, which is the regional-format locale. The Windows builder uses CurrentUICulture, so English Windows with German regional formats gets a German game. GetUserDefaultUILanguage (or GetUserPreferredUILanguages) matches the builder.

Also worth a line in the docs: a plain CLI build into an existing folder now keeps that folder's language instead of resetting to English.

@jarynclouatre

Copy link
Copy Markdown
Contributor Author

Thanks, all three done in 9071c78:

  • Windows: system_language now reads the display language, the first of GetUserPreferredUILanguages (MUI_LANGUAGE_NAME), else LCIDToLocaleName(GetUserDefaultUILanguage()), so it follows the same setting as the builder's CurrentUICulture. On a Windows 11 PC whose display language is English (United States) and regional format English (Canada), it reads en-US (PowerShell's Get-UICulture says en-US, Get-Culture en-CA, and GetUserDefaultLocaleName returned en-CA).
  • Linux: LANGUAGE's first entry comes first, unless the locale from LC_ALL/LC_MESSAGES/LANG is C or POSIX, as gettext does. The test has five more cases for it.
  • The readme's wrong-language line now says an update keeps the code set in language.txt.

tests/test_make_game_prepare.py passes on Linux (17) and on that Windows PC (16, 1 Linux-only skip).

@NotRexed NotRexed mentioned this pull request Nov 11, 2026
3 tasks done

@Joey-Magnus Joey-Magnus left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

9071c78 addresses all three points from my last review.

  • Windows now reads the display language: the first of GetUserPreferredUILanguages (MUI_LANGUAGE_NAME), else LCIDToLocaleName(GetUserDefaultUILanguage()) (windows_ui_language in nx2/make_game.py). That's the setting behind the builder's CurrentUICulture, and your check with an en-US display language and en-CA regional format was the case that mattered.
  • On Linux, LANGUAGE's first entry now comes ahead of LC_ALL/LC_MESSAGES/LANG. It's ignored when the locale is C, POSIX or unset, as gettext does.
  • The readme's "wrong language" row now says an update keeps the language set in language.txt.

tests/test_make_game_prepare.py passes here (17 tests), the branch merges cleanly with current main, and CI is green on the new head. Nothing is left open from my side.

@hckrman101
hckrman101 merged commit e038753 into NotRexed:main Nov 11, 2026
14 checks passed
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.

4 participants