Skip to content

Conversation

confused-Techie
Copy link
Member

@confused-Techie confused-Techie commented Feb 10, 2025

This PR begins the painstaking process of removing strings from Pulsar core and our packages in such a way to allow them to be translated in the future.

While I'm not nearly done with this process yet, it seems to me that this PR has done a lot of heavy lifting in this area and got us started in such a way that now may be a good time to step back and make sure we all agree on the fundamentals of this process.
That way we can try to rule out any potential issues now with a smaller (but still large) PR, rather than having to go back and make major changes if we see any issue with methodology.

So first, I'll lay out some of the basic rules about what I've been doing and the logic behind it:

  1. Only ever translate text intended for the user. This may mean settings, menus, strings on screen, or text that's intended to be displayed in a notification. That does not include any text logged to the console, or intended for Grim deprecations.
  2. It seemed appropriate to have (nearly) all keypaths contain only lower case text, with - for breaking up words. Making the keypath easy to read and differentiate. The only outlier to this is config strings.
  3. When providing strings for configs or menu items, as much as possible the keypath includes the config item or the command related to the menu item, to ensure it's easy to pair up what goes where.
  4. If you have similarly grouped keys, it seems best to create deep objects to contain each part, although originally I did use : to distinguish, I found it easier to use sub-objects and changed them all over.

As for the basic shape of a locale file, for packages, I'd recommend the following top level keys:

  • config: For configuration strings
  • menu: For menu strings
  • context-menu: For context menu strings
  • src: For strings that appear in source code
  • commons: For strings that may be shared across multiple other aspects.

For some large packages it may make sense to even break up the src strings by filename where they appear, but I didn't find that to be required in most cases.
Additionally, for packages I didn't find it necessary to make a commons section all that often.

One very important note I did make, it a commons section in Pulsar's locale file. I think it'd be prudent and beneficial for community packages wanting to localize for use to provide pulsar.commons in the locale namespace, to provide easy access to common strings.
This means we would have to guarantee the stability of these strings, but also means that packages can get common strings translated with no effort by relying on us to do it. Plus it also means less memory usage as we don't have each package defining the same strings over and over again.

As of now, here these are all the commons strings I've defined:

  • proceed: "Proceed"
  • ok: "OK"
  • cancel: "Cancel"
  • skip: "Skip"
  • menu-labels.file: "File"
  • menu-labels.edit: "Edit"
  • menu-labels.view: "View"
  • menu-labels.selection: "Selection"
  • menu-labels.find: "Find"
  • menu-labels.packages: "Packages`
  • menu-labels.help: "Help"

So anything here we would want to always have accessible at the same keypath, and always meaning the same thing.
But I'd also love to expand this out as much as possible.


Lastly, because I know this is a somewhat complicated to review process, and scary one since it can have some big effects, I've decided to create a small tool to help with this process.

pulsar-locale-health-check can help automate some of the checks needed to be confident in this process of changing our packages.

It's able to look at any given package and ensure the following:

  • No duplicate keys in the locale file
  • No errors parsing locale files
  • Every package has the default, required en locale defined
  • It also ensures that every string it finds defined is found in the locale file. Currently it searches the following locations for defined strings:
    • ./menus: Menu items, and Context Menu items
    • ./package.json: Config keys
    • ./src|./lib|index.js: Checks the source code using regex to try and find any usages of the atom.i18n API and extract keys from it.

While it isn't perfect it was good enough to point out some errors I had in my work and help me resolve them.


Below I'll post the complete output of pulsar-locale-health-check and below that will be the checklist of currently localized packages, again not every package has been localized, but a good amount of the simple ones have.

I'll likely decide to break up the other packages into sections based on size and complexity, hoping to make reviewing easier and simpler.

Pulsar Locale Health Check Output

wrap-guide: D:\Personal Documents\GitHub Repositories\pulsar-edit\pulsar\packages\wrap-guide
┌────────────────┬────────┐
│ (index) │ Values │
├────────────────┼────────┤
│ has_duplicates │ false │
│ has_en_locale │ true │
│ has_errors │ false │
│ total_keypaths │ 6 │
└────────────────┴────────┘
KeyPaths Popularity in Package
┌────────────────────────────────────────────────────────────┬────────┐
│ (index) │ Values │
├────────────────────────────────────────────────────────────┼────────┤
│ wrap-guide.config.columns.description │ 1 │
│ wrap-guide.config.modifyPreferredLineLength.description │ 1 │
│ wrap-guide.config.showWrapGuide.description │ 1 │
│ wrap-guide.config.showWrapGuide.enum.always │ 1 │
│ wrap-guide.config.showWrapGuide.enum.wrapping │ 1 │
│ wrap-guide.config.showWrapGuide.enum.atPreferredLineLength │ 1 │
└────────────────────────────────────────────────────────────┴────────┘
whitespace: D:\Personal Documents\GitHub Repositories\pulsar-edit\pulsar\packages\whitespace
┌────────────────┬────────┐
│ (index) │ Values │
├────────────────┼────────┤
│ has_duplicates │ false │
│ has_en_locale │ true │
│ has_errors │ false │
│ total_keypaths │ 12 │
└────────────────┴────────┘
KeyPaths Popularity in Package
┌───────────────────────────────────────────────────────────────┬────────┐
│ (index) │ Values │
├───────────────────────────────────────────────────────────────┼────────┤
│ whitespace.menu.whitespace:label │ 1 │
│ whitespace.menu.whitespace:remove-trailing-whitespace │ 1 │
│ whitespace.menu.whitespace:save-with-trailing-whitespace │ 1 │
│ whitespace.menu.whitespace:save-without-trailing-whitespace │ 1 │
│ whitespace.menu.whitespace:convert-tabs-to-spaces │ 1 │
│ whitespace.menu.whitespace:convert-spaces-to-tabs │ 1 │
│ whitespace.menu.whitespace:convert-all-tabs-to-spaces │ 1 │
│ whitespace.config.removeTrailingWhitespace:description │ 1 │
│ whitespace.config.keepMarkdownLineBreakWhitespace:description │ 1 │
│ whitespace.config.ignoreWhitespaceOnCurrentLine:description │ 1 │
│ whitespace.config.ignoreWhitespaceOnlyLines:description │ 1 │
│ whitespace.config.ensureSingleTrailingNewline:description │ 1 │
└───────────────────────────────────────────────────────────────┴────────┘
update-package-dependencies: D:\Personal Documents\GitHub Repositories\pulsar-edit\pulsar\packages\update-package-dependencies
┌────────────────┬────────┐
│ (index) │ Values │
├────────────────┼────────┤
│ has_duplicates │ false │
│ has_en_locale │ true │
│ has_errors │ false │
│ total_keypaths │ 3 │
└────────────────┴────────┘
KeyPaths Popularity in Package
┌───────────────────────────────────────────────────────┬────────┐
│ (index) │ Values │
├───────────────────────────────────────────────────────┼────────┤
│ update-package-dependencies.src.updating-package-deps │ 1 │
│ update-package-dependencies.src.update-deps:success │ 1 │
│ update-package-dependencies.src.update-deps:failure │ 1 │
└───────────────────────────────────────────────────────┴────────┘
tree-view: D:\Personal Documents\GitHub Repositories\pulsar-edit\pulsar\packages\tree-view
┌────────────────┬────────┐
│ (index) │ Values │
├────────────────┼────────┤
│ has_duplicates │ false │
│ has_en_locale │ true │
│ has_errors │ false │
│ total_keypaths │ 61 │
└────────────────┴────────┘
KeyPaths Popularity in Package
┌──────────────────────────────────────────────────────┬────────┐
│ (index) │ Values │
├──────────────────────────────────────────────────────┼────────┤
│ tree-view.menu.tree-view:toggle │ 1 │
│ tree-view.menu.packages.label │ 1 │
│ tree-view.menu.packages.tree-view:toggle-focus │ 1 │
│ tree-view.menu.packages.tree-view:toggle │ 1 │
│ tree-view.menu.packages.tree-view:reveal-active-file │ 1 │
│ tree-view.menu.packages.tree-view:toggle-side │ 1 │
│ tree-view.context-menu.new-file │ 2 │
│ tree-view.context-menu.new-folder │ 2 │
│ tree-view.context-menu.rename │ 3 │
│ tree-view.context-menu.duplicate │ 2 │
│ tree-view.context-menu.delete │ 2 │
│ tree-view.context-menu.copy │ 2 │
│ tree-view.context-menu.cut │ 2 │
│ tree-view.context-menu.paste │ 2 │
│ tree-view.context-menu.add-project-folder │ 1 │
│ tree-view.context-menu.remove-project-folder │ 1 │
│ tree-view.context-menu.collapse-all-project-folders │ 1 │
│ tree-view.context-menu.copy-full-path │ 1 │
│ tree-view.context-menu.copy-project-path │ 1 │
│ tree-view.context-menu.open-in-new-window │ 1 │
│ tree-view.context-menu.reveal-in-finder │ 3 │
│ tree-view.context-menu.reveal-in-explorer │ 3 │
│ tree-view.context-menu.reveal-in-file-manager │ 3 │
│ tree-view.context-menu.reveal-in-tree-view │ 2 │
│ tree-view.config.squashDirectoryNames.title │ 1 │
│ tree-view.config.squashDirectoryNames.description │ 1 │
│ tree-view.config.hideVcsIgnoredFiles.title │ 1 │
│ tree-view.config.hideVcsIgnoredFiles.description │ 1 │
│ tree-view.config.hideIgnoredNames.description │ 1 │
│ tree-view.config.sortFoldersBeforeFiles.description │ 1 │
│ tree-view.config.autoReveal.description │ 1 │
│ tree-view.config.focusOnReveal.description │ 1 │
│ tree-view.config.alwaysOpenExisting.description │ 1 │
│ tree-view.config.hiddenOnStartup.description │ 1 │
│ tree-view.src.enter-new-path-prompt │ 1 │
│ tree-view.src.root-project-path-is-null │ 1 │
│ tree-view.src.file-already-exists │ 4 │
│ tree-view.src.ends-with-directory-separator │ 1 │
│ tree-view.src.project-is-empty │ 1 │
│ tree-view.src.add-folders │ 1 │
│ tree-view.src.reopen-project │ 1 │
│ tree-view.src.enter-new-path-for-dup │ 1 │
│ tree-view.src.error-parsing-ignore-pattern │ 1 │
│ tree-view.src.enter-new-path.dir │ 1 │
│ tree-view.src.enter-new-path.file │ 1 │
│ tree-view.src.cannot-move-with-multiple-roots │ 1 │
│ tree-view.src.unable-to-show-file │ 2 │
│ tree-view.src.root-dir-cannot-be-removed │ 1 │
│ tree-view.src.are-you-sure-you-want-to-delete.msg │ 1 │
│ tree-view.src.are-you-sure-you-want-to-delete.detail │ 1 │
│ tree-view.src.move-to-trash │ 1 │
│ tree-view.src.cannot-move-to-trash │ 1 │
│ tree-view.src.trash-enabled-msg.linux │ 1 │
│ tree-view.src.trash-enabled-msg.darwin │ 1 │
│ tree-view.src.trash-enabled-msg.win32 │ 1 │
│ tree-view.src.cannot-copy-dir-into-itself │ 1 │
│ tree-view.src.failed-to-copy │ 1 │
│ tree-view.src.cannot-move-dir-into-itself │ 1 │
│ tree-view.src.failed-to-move │ 3 │
│ tree-view.src.want-to-replace │ 1 │
│ tree-view.src.replace-file │ 1 │
└──────────────────────────────────────────────────────┴────────┘
timecop: D:\Personal Documents\GitHub Repositories\pulsar-edit\pulsar\packages\timecop\

===NOTE=== These errors are a false positive ===NOTE===
┌────────────────┬────────┐
│ (index) │ Values │
├────────────────┼────────┤
│ has_duplicates │ false │
│ has_en_locale │ true │
│ has_errors │ true │
│ total_keypaths │ 7 │
└────────────────┴────────┘
Errors
┌─────────┬───────────────────────────────────────────────────────────────────────────────────────────────┐
│ (index) │ Values │
├─────────┼───────────────────────────────────────────────────────────────────────────────────────────────┤
│ 0 │ "The keypath 'cache-panel-view.compile-cache' is present in the locale file but never used." │
│ 1 │ "The keypath 'cache-panel-view.files-compiled' is present in the locale file but never used." │
└─────────┴───────────────────────────────────────────────────────────────────────────────────────────────┘
KeyPaths Popularity in Package
┌────────────────────────────────────────┬────────┐
│ (index) │ Values │
├────────────────────────────────────────┼────────┤
│ timecop.menu.timecop:label │ 1 │
│ timecop.menu.timecop:view │ 1 │
│ timecop.common.loading │ 5 │
│ timecop.window-panel-view.startup-time │ 1 │
│ timecop.window-panel-view.load-time │ 4 │
└────────────────────────────────────────┴────────┘
tabs: D:\Personal Documents\GitHub Repositories\pulsar-edit\pulsar\packages\tabs
┌────────────────┬────────┐
│ (index) │ Values │
├────────────────┼────────┤
│ has_duplicates │ false │
│ has_en_locale │ true │
│ has_errors │ false │
│ total_keypaths │ 25 │
└────────────────┴────────┘
KeyPaths Popularity in Package
┌───────────────────────────────────────────────┬────────┐
│ (index) │ Values │
├───────────────────────────────────────────────┼────────┤
│ tabs.menu.tabs:close-all-tabs │ 1 │
│ tabs.context-menu.tabs:close-tab │ 1 │
│ tabs.context-menu.tabs:close-other-tabs │ 1 │
│ tabs.context-menu.tabs:close-tabs-to-right │ 1 │
│ tabs.context-menu.tabs:close-tabs-to-left │ 1 │
│ tabs.context-menu.tabs:close-saved-tabs │ 1 │
│ tabs.context-menu.tabs:close-all-tabs │ 1 │
│ tabs.context-menu.tabs:split-up │ 1 │
│ tabs.context-menu.tabs:split-down │ 1 │
│ tabs.context-menu.tabs:split-left │ 1 │
│ tabs.context-menu.tabs:split-right │ 1 │
│ tabs.context-menu.tabs:open-in-new-window │ 1 │
│ tabs.context-menu.tabs:keep-pending-tab │ 1 │
│ tabs.context-menu.pane:reopen-closed-item │ 1 │
│ tabs.config.showIcons.description │ 1 │
│ tabs.config.alwaysShowTabBar.description │ 1 │
│ tabs.config.tabScrolling.description │ 1 │
│ tabs.config.tabScrollingThreshold.description │ 1 │
│ tabs.config.enableVcsColoring.title │ 1 │
│ tabs.config.enableVcsColoring.description │ 1 │
│ tabs.config.addNewTabsAtEnd.description │ 1 │
│ tabs.config.enableMruTabSwitching.title │ 1 │
│ tabs.config.enableMruTabSwitching.description │ 1 │
│ tabs.config.displayMruTabList.title │ 1 │
│ tabs.config.displayMruTabList.description │ 1 │
└───────────────────────────────────────────────┴────────┘
link: D:\Personal Documents\GitHub Repositories\pulsar-edit\pulsar\packages\link
┌────────────────┬────────┐
│ (index) │ Values │
├────────────────┼────────┤
│ has_duplicates │ false │
│ has_en_locale │ true │
│ has_errors │ false │
│ total_keypaths │ 1 │
└────────────────┴────────┘
KeyPaths Popularity in Package
┌─────────────────────────────┬────────┐
│ (index) │ Values │
├─────────────────────────────┼────────┤
│ link.context-menu.link:open │ 1 │
└─────────────────────────────┴────────┘
line-ending-selector: D:\Personal Documents\GitHub Repositories\pulsar-edit\pulsar\packages\line-ending-selector
┌────────────────┬────────┐
│ (index) │ Values │
├────────────────┼────────┤
│ has_duplicates │ false │
│ has_en_locale │ true │
│ has_errors │ false │
│ total_keypaths │ 3 │
└────────────────┴────────┘
KeyPaths Popularity in Package
┌───────────────────────────────────────────────────────────┬────────┐
│ (index) │ Values │
├───────────────────────────────────────────────────────────┼────────┤
│ line-ending-selector.config.defaultLineEnding.title │ 1 │
│ line-ending-selector.config.defaultLineEnding.description │ 1 │
│ line-ending-selector.src.file-uses │ 1 │
└───────────────────────────────────────────────────────────┴────────┘
grammar-selector: D:\Personal Documents\GitHub Repositories\pulsar-edit\pulsar\packages\grammar-selector
┌────────────────┬────────┐
│ (index) │ Values │
├────────────────┼────────┤
│ has_duplicates │ false │
│ has_en_locale │ true │
│ has_errors │ false │
│ total_keypaths │ 7 │
└────────────────┴────────┘
KeyPaths Popularity in Package
┌───────────────────────────────────────────────────────────────────┬────────┐
│ (index) │ Values │
├───────────────────────────────────────────────────────────────────┼────────┤
│ grammar-selector.menu.select-grammar:label │ 1 │
│ grammar-selector.context-menu.grammar-selector:show:label │ 1 │
│ grammar-selector.config.showOnRightSideOfStatusBar.description │ 1 │
│ grammar-selector.config.hideDuplicateTextMateGrammars.title │ 1 │
│ grammar-selector.config.hideDuplicateTextMateGrammars.description │ 1 │
│ grammar-selector.src.wasm-tree-sitter-parser:title │ 1 │
│ grammar-selector.src.file-uses-grammar │ 1 │
└───────────────────────────────────────────────────────────────────┴────────┘
go-to-line: D:\Personal Documents\GitHub Repositories\pulsar-edit\pulsar\packages\go-to-line
┌────────────────┬────────┐
│ (index) │ Values │
├────────────────┼────────┤
│ has_duplicates │ false │
│ has_en_locale │ true │
│ has_errors │ false │
│ total_keypaths │ 2 │
└────────────────┴────────┘
KeyPaths Popularity in Package
┌──────────────────────────────────┬────────┐
│ (index) │ Values │
├──────────────────────────────────┼────────┤
│ go-to-line.menu.go-to-line:label │ 1 │
│ go-to-line.src.open-message │ 1 │
└──────────────────────────────────┴────────┘
dev-live-reload: D:\Personal Documents\GitHub Repositories\pulsar-edit\pulsar\packages\dev-live-reload
┌────────────────┬────────┐
│ (index) │ Values │
├────────────────┼────────┤
│ has_duplicates │ false │
│ has_en_locale │ true │
│ has_errors │ false │
│ total_keypaths │ 2 │
└────────────────┴────────┘
KeyPaths Popularity in Package
┌───────────────────────────────────────────────────────┬────────┐
│ (index) │ Values │
├───────────────────────────────────────────────────────┼────────┤
│ dev-live-reload.menu.label │ 1 │
│ dev-live-reload.menu.dev-live-reload:reload-all:label │ 1 │
└───────────────────────────────────────────────────────┴────────┘
command-palette: D:\Personal Documents\GitHub Repositories\pulsar-edit\pulsar\packages\command-palette
┌────────────────┬────────┐
│ (index) │ Values │
├────────────────┼────────┤
│ has_duplicates │ false │
│ has_en_locale │ true │
│ has_errors │ false │
│ total_keypaths │ 7 │
└────────────────┴────────┘
KeyPaths Popularity in Package
┌───────────────────────────────────────────────────────┬────────┐
│ (index) │ Values │
├───────────────────────────────────────────────────────┼────────┤
│ command-palette.menu.view:command-palette:toggle │ 1 │
│ command-palette.menu.packages:command-palette │ 1 │
│ command-palette.menu.packages:commnd-palette:toggle │ 1 │
│ command-palette.config.preserveLastSearch:description │ 1 │
│ command-palette.commandPaletteView.emptyMessage │ 1 │
│ command-palette.commandPaletteView.matchingTags │ 1 │
│ command-palette.commandPaletteView.commaSpace │ 1 │
└───────────────────────────────────────────────────────┴────────┘
bracket-matcher: D:\Personal Documents\GitHub Repositories\pulsar-edit\pulsar\packages\bracket-matcher
┌────────────────┬────────┐
│ (index) │ Values │
├────────────────┼────────┤
│ has_duplicates │ false │
│ has_en_locale │ true │
│ has_errors │ false │
│ total_keypaths │ 13 │
└────────────────┴────────┘
KeyPaths Popularity in Package
┌────────────────────────────────────────────────────────────────┬────────┐
│ (index) │ Values │
├────────────────────────────────────────────────────────────────┼────────┤
│ bracket-matcher.menu.bracket-matcher:label │ 1 │
│ bracket-matcher.menu.go-to-matching-bracket │ 1 │
│ bracket-matcher.menu.select-inside-brackets │ 2 │
│ bracket-matcher.menu.remove-brackets-from-selection │ 1 │
│ bracket-matcher.menu.close-tag │ 1 │
│ bracket-matcher.menu.remove-matching-brackets │ 1 │
│ bracket-matcher.menu.select-matching-brackets │ 1 │
│ bracket-matcher.config.autocompleteCharacters:description │ 1 │
│ bracket-matcher.config.pairsWithExtraNewline:description │ 1 │
│ bracket-matcher.config.autocompleteBrackets:description │ 1 │
│ bracket-matcher.config.wrapSelectionsInBrackets:description │ 1 │
│ bracket-matcher.config.highlightMatchingLineNumber:description │ 1 │
│ bracket-matcher.config.alwaysSkipClosingPairs:description │ 1 │
└────────────────────────────────────────────────────────────────┴────────┘
bookmarks: D:\Personal Documents\GitHub Repositories\pulsar-edit\pulsar\packages\bookmarks
┌────────────────┬────────┐
│ (index) │ Values │
├────────────────┼────────┤
│ has_duplicates │ false │
│ has_en_locale │ true │
│ has_errors │ false │
│ total_keypaths │ 9 │
└────────────────┴────────┘
KeyPaths Popularity in Package
┌────────────────────────────────────────────┬────────┐
│ (index) │ Values │
├────────────────────────────────────────────┼────────┤
│ bookmarks.menu.bookmark:label │ 1 │
│ bookmarks.menu.view-all │ 1 │
│ bookmarks.menu.toggle-bookmark │ 2 │
│ bookmarks.menu.jump-to-next-bookmark │ 1 │
│ bookmarks.menu.jump-to-previous-bookmark │ 1 │
│ bookmarks.menu.select-to-next-bookmark │ 1 │
│ bookmarks.menu.select-to-previous-bookmark │ 1 │
│ bookmarks.bookmarksView.no-bookmarks-found │ 1 │
│ bookmarks.bookmarksView.untitled │ 1 │
└────────────────────────────────────────────┴────────┘
background-tips: D:\Personal Documents\GitHub Repositories\pulsar-edit\pulsar\packages\background-tips\

===NOTE=== The errors here are false positives ===NOTE===
┌────────────────┬────────┐
│ (index) │ Values │
├────────────────┼────────┤
│ has_duplicates │ false │
│ has_en_locale │ true │
│ has_errors │ true │
│ total_keypaths │ 12 │
└────────────────┴────────┘
Errors
┌─────────┬───────────────────────────────────────────────────────────────────────┐
│ (index) │ Values │
├─────────┼───────────────────────────────────────────────────────────────────────┤
│ 0 │ "The keypath 'tips.1' is present in the locale file but never used." │
│ 1 │ "The keypath 'tips.2' is present in the locale file but never used." │
│ 2 │ "The keypath 'tips.3' is present in the locale file but never used." │
│ 3 │ "The keypath 'tips.4' is present in the locale file but never used." │
│ 4 │ "The keypath 'tips.5' is present in the locale file but never used." │
│ 5 │ "The keypath 'tips.6' is present in the locale file but never used." │
│ 6 │ "The keypath 'tips.7' is present in the locale file but never used." │
│ 7 │ "The keypath 'tips.8' is present in the locale file but never used." │
│ 8 │ "The keypath 'tips.9' is present in the locale file but never used." │
│ 9 │ "The keypath 'tips.10' is present in the locale file but never used." │
│ 10 │ "The keypath 'tips.11' is present in the locale file but never used." │
│ 11 │ "The keypath 'tips.12' is present in the locale file but never used." │
└─────────┴───────────────────────────────────────────────────────────────────────┘
KeyPaths Popularity in Package
┌─────────┐
│ (index) │
├─────────┤
└─────────┘
autosave: D:\Personal Documents\GitHub Repositories\pulsar-edit\pulsar\packages\autosave
┌────────────────┬────────┐
│ (index) │ Values │
├────────────────┼────────┤
│ has_duplicates │ false │
│ has_en_locale │ true │
│ has_errors │ false │
│ total_keypaths │ 1 │
└────────────────┴────────┘
KeyPaths Popularity in Package
┌───────────────────────────────┬────────┐
│ (index) │ Values │
├───────────────────────────────┼────────┤
│ autosave.config.enabled.title │ 1 │
└───────────────────────────────┴────────┘
autoflow: D:\Personal Documents\GitHub Repositories\pulsar-edit\pulsar\packages\autoflow
┌────────────────┬────────┐
│ (index) │ Values │
├────────────────┼────────┤
│ has_duplicates │ false │
│ has_en_locale │ true │
│ has_errors │ false │
│ total_keypaths │ 1 │
└────────────────┴────────┘
KeyPaths Popularity in Package
┌─────────────────────────────────────┬────────┐
│ (index) │ Values │
├─────────────────────────────────────┼────────┤
│ autoflow.menu.reflowSelection:label │ 1 │
└─────────────────────────────────────┴────────┘
about: D:\Personal Documents\GitHub Repositories\pulsar-edit\pulsar\packages\about
┌────────────────┬────────┐
│ (index) │ Values │
├────────────────┼────────┤
│ has_duplicates │ false │
│ has_en_locale │ true │
│ has_errors │ false │
│ total_keypaths │ 9 │
└────────────────┴────────┘
KeyPaths Popularity in Package
┌───────────────────────────────────┬────────┐
│ (index) │ Values │
├───────────────────────────────────┼────────┤
│ about.src.show-more │ 3 │
│ about.src.hide │ 2 │
│ about.src.release-notes │ 1 │
│ about.src.updates-have-been-moved │ 1 │
│ about.src.how-to-update │ 1 │
│ about.src.license │ 1 │
│ about.src.enable-pulsar-updater │ 1 │
│ about.src.check-now │ 1 │
│ about.src.about-title │ 1 │
└───────────────────────────────────┴────────┘
archive-view: D:\Personal Documents\GitHub Repositories\pulsar-edit\pulsar\packages\archive-view
┌────────────────┬────────┐
│ (index) │ Values │
├────────────────┼────────┤
│ has_duplicates │ false │
│ has_en_locale │ true │
│ has_errors │ false │
│ total_keypaths │ 3 │
└────────────────┴────────┘
KeyPaths Popularity in Package
┌───────────────────────────────────────────────────────┬────────┐
│ (index) │ Values │
├───────────────────────────────────────────────────────┼────────┤
│ archive-view.archive-editor-view.loadingArchive │ 1 │
│ archive-view.archive-editor-view.untitled │ 1 │
│ archive-view.archive-editor-view.readingArchiveFailed │ 1 │
└───────────────────────────────────────────────────────┴────────┘
Pulsar Commons
┌───────────────────────────────┬────────┐
│ (index) │ Values │
├───────────────────────────────┼────────┤
│ commons.menu-labels.packages │ 6 │
│ commons.menu-labels.view │ 2 │
│ commons.ok │ 1 │
│ commons.cancel │ 2 │
│ commons.skip │ 1 │
│ commons.menu-labels.file │ 1 │
│ commons.menu-labels.edit │ 4 │
│ commons.menu-labels.selection │ 1 │
└───────────────────────────────┴────────┘

Checklist of Localized Packages
  • about
  • archive-view [PARTIAL]
  • atom-dark-syntax
  • atom-dark-ui
  • atom-light-syntax
  • atom-light-ui
  • autocomplete-atom-api
  • autocomplete-css [Should parts of completions be localized if they aren't?]
  • autocomplete-html
  • autocomplete-plus
  • autocomplte-snippets
  • autoflow
  • autosave
  • background-tips
  • base16-tomorrow-dark-theme
  • base16-tomorrow-light-theme
  • bookmarks
  • bracket-matcher
  • command-palette
  • dalek
  • deprecation-cop
  • dev-live-reload
  • encoding-selector
  • exception-reporting
  • find-and-replace
  • fuzzy-finder
  • git-diff
  • go-to-line
  • grammar-selector
  • image-view
  • incompatible-packages
  • keybinding-resolver
  • language-c
  • language-clojure
  • language-coffee-script
  • language-csharp
  • language-css
  • language-gfm
  • language-git
  • language-go
  • language-html
  • language-hyperlink
  • language-java
  • language-javascript
  • language-json
  • language-less
  • language-make
  • language-mustache
  • language-objective-c
  • language-perl
  • language-php
  • language-property-list
  • language-python
  • language-ruby
  • language-ruby-on-rails
  • language-rust-bundled
  • language-sass
  • language-shellscript
  • language-source
  • language-sql
  • language-text
  • language-toto
  • language-toml
  • language-typescript
  • language-xml
  • language-yaml
  • line-ending-selector
  • link
  • markdown-preview
  • notifications
  • one-dark-syntax
  • one-dark-ui
  • one-light-syntax
  • one-light-ui
  • open-on-github
  • package-generator
  • pulsar-updater
  • settings-view
  • snippets
  • solarized-dark-syntax
  • solarized-light-syntax
  • spell-check
  • status-bar
  • styleguide
  • symbol-provider-ctags
  • symbol-provider-tree-sitter
  • symbols-view
  • tabs
  • timecop
  • tree-view
  • update-pacakge-dependencies
  • welcome
  • whitespace
  • wrap-guide

Lastly, some helpful notes about writing so much text in CSON files, that'll then be interpreted by the Intl-MessageFormat:

  • If you want a ' to appear in your text, you must use \'\'. Such as: Output = 'Hello '{data}'', Input CSON = 'Hello \'\'{data}\'\''
  • If you want a newline to appear in your text, you must use \\\n

@savetheclocktower
Copy link
Contributor

@confused-Techie, please check your Discord DMs when you get a chance — I've got a quick favor to ask. Thanks!

@confused-Techie
Copy link
Member Author

I'm logging off for the night, but while working on this I've come up with some very rough draft notes for how our localization's are handled. I'll go ahead and add them here:

Localization naming guide:

We have our top most sections:

* config: For configuration items
* menu: For menu items
* context-menu: For context menu items
* src: Optional, for strings that appear in the source code
* commons: The Pulsar common strings, API stable, accessible to community packages for simple agnostic strings

If you have a lot of the other top level keys, then `src` can be helpful, but if you don't you likely don't 
need that key.

Generally it may be a good idea to have the file name as the parent key.

Keys should have no capitalization, using `-` as separators.

If you have to similar keys, then `:` can be used to differentiate.
Such as a notification error that has a message and detail component:

* `notification-error:message`
* `notification-error:detail`

---

What not to localize?

It's probably best to only localize what is intended to be shown to users. This means any text on screen,
or that will appear as a notification.

So text that's logged to console should probably be left as is, as well as deprecation messages.

---

Important Note:

If you want a string to read as: "A string with flexible 'data'"

You'd initially expect to be able to make a localized string like: "A string with flexible '{data}'"
And provide a replacement value for 'data'

But since these files are usually written in CoffeeScript you need to write it like: 'A string with flexible '{data}''

Which of course needs to be escaped like: 'A string with flexible \'{data}\''

But lastly, because the ICU Message Syntax treats a "'" as an escape, you need to use double "''" to tell ICU
that you want the "'" to appear. So your localized string should actually be:
'A string with flexible \'\'{data}\'\''

A bit cumbersome, but very good to know

@confused-Techie
Copy link
Member Author

Just want to point out, while working on this PR, I discovered some big bugs in our rolling release that were created by my other I18n PR.
Namely, that bundled packages weren't getting their menus, or context-menus localized, nor for that matter was Pulsar itself.

In this PR, the last few commits namely, I was able to finally fix this issue by changing what metadata we bundled within the package's during the package cache stage, and to add some preloading of I18n strings (as well as some slight adjustments to when in the lifecycle I18n is actually setup).

While I'm hoping we could get this merged before we bring that rolling to regular, just want to point that out here for anyone running rolling that's seeing those issues. So rest assured they are 100% solved here

@confused-Techie confused-Techie marked this pull request as ready for review September 18, 2025 00:21
@confused-Techie
Copy link
Member Author

I've gone ahead and changed this PR to ready to review. While I'm not done localizing all packages, it seemed to me that this may be a good stopping point for all of us to review and agree on things before going further, which should likely happen in multiple smaller PRs, rather than one huge PR.

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