Skip to content

chore: add English strings and restore CFBundleLocalizations#280

Merged
xor-gate merged 4 commits intosyncthing:v2from
vegca:add-en-lproj-weblate-prep
Mar 15, 2026
Merged

chore: add English strings and restore CFBundleLocalizations#280
xor-gate merged 4 commits intosyncthing:v2from
vegca:add-en-lproj-weblate-prep

Conversation

@vegca
Copy link
Contributor

@vegca vegca commented Mar 10, 2026

  • Add en.lproj/ with English .strings files (generated from Base.lproj XIBs using
    ibtool and changing them to UTF-8) so that English is an explicit localization alongside Spanish.

  • Restore CFBundleLocalizations in Info.plist (probably accidentally removed in a later commit).

  • Add en.lproj files in the Xcode project (PBXFileReference + PBXVariantGroup entries).

This prepares the project structure for integration with Syncthing's Hosted Weblate, which needs .strings source files for each translatable component. With en.lproj/ as the base and es.lproj/ as the existing translation, Weblate should be able to manage both and accept contributions for new languages.

As a secondary benefit (later :P), expanding the set of supported localizations reduces the likelihood of the scenario described in #277, where a user whose primary language is not yet supported may see the app in an unintended language due to an accidental secondary-language match. The more languages are covered, the less often this edge case arises.

Related discussion: #238

Tests

  • make debug builds successfully
  • open Syncthing.app --args -AppleLanguages '(en)' — menu shows English
  • open Syncthing.app --args -AppleLanguages '(es)' — menu shows Spanish

Comment on lines +7 to +11
<key>CFBundleLocalizations</key>
<array>
<string>en</string>
<string>es</string>
</array>
Copy link
Member

Choose a reason for hiding this comment

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

The Info.plist is not the actual file. You need to update the Info.plist.tmpl, which is used as input for injecting the Syncthing version via cmd/update-release/update-release.py. Maybe that is why it was broken :-). But you could not know the release management helper script.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah, I wasn't aware of that template workflow.

Anyway, just to clarify: CFBundleLocalizations isn't/wasn't technically broken since that's optional (macOS auto-detects localizations from the .lproj directories in the bundle). Everything is working as intended, but explicitly declaring it is a good practice, and adding it to the template ensures it persists across releases.

I'll update Info.plist.tmpl to include the CFBundleLocalizations key as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This PR is more in preparation for a future Weblate integration since we need a base language.

@acolomb
Copy link
Member

acolomb commented Mar 11, 2026

I'm a bit confused, why do we need the en.lproj stuff which is basically just a copy of Base.lproj? If the "source" language is English, then the "base" file should be the English localization. Duplicating it does not make integration on Weblate easier I think.

@acolomb
Copy link
Member

acolomb commented Mar 11, 2026

I just tried to set it up in Weblate for testing, but this PR branch fails because both "Base" and "en" are detected as English language for the Localizable.strings resource. Should this duplication simply be skipped in en.lproj (or maybe in Base.lproj instead)? For the other files, I see that there is actually Base.lproj/*.xib vs. en.lproj/*.strings, so these are correctly separated already.

I've started reading up on how XCode usually does this here: https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPInternational/MaintaingYourOwnStringsFiles/MaintaingYourOwnStringsFiles.html

@vegca
Copy link
Contributor Author

vegca commented Mar 11, 2026

Yep, that’s right. I didn’t really want to mess with those other files, but en.lproj/Localizable.strings is an unnecessary duplicate since Base.lproj/Localizable.strings already serves as the English source in .strings format.

But I think the other 4 files in en.lproj/ (STApplication.strings, STAboutWindow.strings, etc.) are still needed as their Base.lproj counterparts are .xib files, not .strings, so there's no duplication there. I remember reading that Weblate uses .string files and doesn't support xib files, right?

I need to look into it, maybe merging them.

@acolomb
Copy link
Member

acolomb commented Mar 11, 2026

AIUI, the .xib / .strings part is correct, yes. For consistency though, I think all the generated English *.strings files should end up in one place, namely en.lproj. But then the workflow for extracting strings from source needs to be changed to place the result there instead of Base.lproj.

@vegca
Copy link
Contributor Author

vegca commented Mar 11, 2026

I've moved Localizable.strings from Base.lproj/ to en.lproj/ so that all English .strings files live in one place. Base.lproj/ now only contains the layout (.xib files)

@acolomb
Copy link
Member

acolomb commented Mar 11, 2026

You didn't remove the actual file though, only the manifest entry?

Where does this file come from anyway? I suppose from some automatic string extraction build step. Which means there is some build configuration to adjust as well?

@xor-gate
Copy link
Member

xor-gate commented Mar 11, 2026

Thanks for all the effort! I would like to see all language folders into a new syncthing/lang/* or else it will get messy.

@vegca
Copy link
Contributor Author

vegca commented Mar 11, 2026

@acolomb Sorry, the file deletion wasn't staged. It's fixed now. Localizable.strings is manually maintained, there's no genstrings build step, so no build configuration to adjust.

@xor-gate The current structure already keeps things separated: Base.lproj/ only contains layouts (.xib), while each language .lproj/ only contains .strings files. So I think it should stay manageable as more languages are added.

@acolomb
Copy link
Member

acolomb commented Mar 11, 2026

I guess the request was about not littering the syncthing/ directory tree with language codes directly. en and es are nicely placed close to each other, but fr and sv will end up among other files in alphabetical sort order. Thus I can understand and do support the request to group them in a subdirectory. Hope that XCode copes well with such a setup.

Not extracting strings automatically is a major drawback of this l10n integration.

@vegca
Copy link
Contributor Author

vegca commented Mar 11, 2026

Moving .lproj directories into a lang/ subdirectory is technically possible, but it goes against Apple's standard project conventions and may break Xcode's built-in localization tooling (adding languages, exporting/importing localizations).
The current layout is the standard and recommended way.

@vegca
Copy link
Contributor Author

vegca commented Mar 11, 2026

@acolomb I mean, English was a manual step (an exception) because it was the base lang but adding a new lang involves Xcode as XIB-derived strings (STApplication.strings, STAboutWindow.strings, etc.) are auto-generated by Xcode when adding a new language

@acolomb
Copy link
Member

acolomb commented Mar 11, 2026

Yes, I know the ones from *.xib are generated automatically. But the Localizable.strings should be extracted as well. Using XCode or whatever command line tool it uses in the background.

Some more context than the previously posted link: https://developer.apple.com/documentation/xcode/localizing-and-varying-text-with-a-string-catalog

It seems the standard location for XCode projects is under Resources/, so we are already deviating from that. Sorry I cannot help at all with XCode-related stuff though. No Apple hardware or software whatsoever in reach... 🤷‍♂️

@vegca
Copy link
Contributor Author

vegca commented Mar 11, 2026

Resources is the standard path in the final bundle (Syncthing.app/Contents/Resources/), not in the source tree. Xcode copies the .lproj directories there automatically during build. As we have now (also pointed in your first link) is the standard convention.

About automated extraction of Localizable.strings, you're right, that could be improved. genstrings can extract NSLocalizedString() keys from source, but it's a manual step. Apple's newer String Catalogs (.xcstrings, Xcode 15+) would solve this automatically, but migrating to that is a bigger change

Maybe we could do some intermediate Python script or something?

@acolomb
Copy link
Member

acolomb commented Mar 11, 2026

This can't be the first project wanting to extract l10n strings during an integrated build step?

Careful with the newer XCode string catalogs format. If it is the same as used in iOS, then there is no support in Weblate for it. It violates the basic assumption of one file per language IIRC. That's blocking us from integrating the pixelspark/sushitrain iOS app into our Weblate project, unfortunately.

@acolomb acolomb changed the title Add en.lproj strings and restore CFBundleLocalizations for Weblate integration chore: add English strings and restore CFBundleLocalizations Mar 13, 2026
Copy link
Member

@xor-gate xor-gate left a comment

Choose a reason for hiding this comment

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

My comment stills stand please move ‎syncthing/en.lproj into syncthing/lang and the other/upcomming .lproj folders.

@vegca
Copy link
Contributor Author

vegca commented Mar 15, 2026

My comment stills stand please move ‎syncthing/en.lproj into syncthing/lang and the other/upcomming .lproj folders.

When adding a new language via "Add Localization" (Project -> Info -> +), Xcode automatically creates the .lproj folder, generates .strings from XIBs, and updates project.pbxproj, all pointing to the standard location.

Moving to lang/ is doable but would mean manually relocating files and fixing project references every time a language is added.

That said, I have no problem moving them if you think it's worth the trade-off.

@xor-gate
Copy link
Member

@vegca thanks for the info, we will leave it this way for the few languages we now have. When the weblate is emitting many languages and want to have clean folders we see then at that point. Thanks for the effort you'all put into this.

@xor-gate xor-gate merged commit 0359f03 into syncthing:v2 Mar 15, 2026
3 checks passed
@acolomb
Copy link
Member

acolomb commented Mar 15, 2026

I don't think we'll have the Weblate component automatically adding languages here. That will be a manual process, because of all the needed references inside XCode files, instead of simply adding a new file per language.

So XCode will definitely be involved, right? If so, it would be cumbersome having to move each new l10n directory under a new path afterwards. I wouldn't recommend it. It goes "against the grain" of the used tooling, which is asking for complications sooner or later.

Having said that, if you still prefer the move, then we should decide right now, so the Weblate stuff can go live with the final configuration.

@vegca
Copy link
Contributor Author

vegca commented Mar 16, 2026

Xcode is not strictly required. The string files can be generated via command-line tools (ibtool --export-strings-file for XIB-derived strings and genstrings for NSLocalizedString() keys). The only tedious part without Xcode is updating project.pbxproj manually... but it should be doable and scriptable.

That said, I agree with keeping the .lproj directories in their current location. Going against the standard tooling conventions tends to cause friction over time.

Regarding lang/: I actually had those changes ready locally right after the merge, so if the decision is made to move them later, the work is already done. But I wouldn't recommend it for the reasons above.

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.

3 participants