Skip to content

How to add and modify Strings

roux g. buciu edited this page Aug 27, 2024 · 16 revisions

How to add new string

For documentation on how the string import and export is done, please see this wiki page.

This file contains all the strings which gets localized for Firefox iOS. To preserve a clean structure of this string file, we should organize them alphabetically, according to specific screens or feature, on that screen. Each string should be under a struct giving a clear indication as to where it is being used. In this case we will prefer verbosity for the sake of accuracy, over brevity. Sub structs may, and should, also be used to separate functionality where it makes sense, but efforts should be made to keep structs two levels deep unless there are good reasons for doing otherwise. As we continue to update strings, old strings may be present at the bottom of this file without this specific structure, which will be updated in due time.

Note that strings shouldn't be reused in multiple places in the application. Depending on the Locale we can't guarantee one string will be translated the same even if its value is the same.

Steps

  1. Create or find the proper struct to add those strings in. If there's no struct that fits in, create one related to the feature or section this string will be under following the guidelines explained above.
  2. Create the new MZLocalizedString under this struct making sure it follows the documentation. Particularly make sure that:
    • The key has a clear explicit name following the structure of where it is located, ended with the version of the app the string was included in (this version is for the build the strings are going into, not their release). This is to ensure that we can easily modify that string if needed later on, as well as monitoring string import PRs easily. The key should always have a version, whether modifying a string, or adding a new string.
    • The tableName is defined and not nil. Generally, the tabelName value should be the upper level struct of the feature. So, for example, if a string is used in .Settings.Wallpapers.StringName the tableName would be Settings.
    • The value is defined and not nil.
    • The comment follows the l10n guidelines.
  3. Once all new strings are added, open a PR on Firefox for iOS.
  4. Once merged, the new strings will be exported automatically to the Firefox l10n repository through the next automated Github action.

Example

Any new string should have the same structure as the following example.

public static let TurnOnNotificationsTitle = MZLocalizedString(
    key: "Settings.Notifications.TurnOnNotificationsTitle.v112",
    tableName: "Settings",
    value: "Turn on Notifications",
    comment: "This is the title informing the user needs to turn on notifications in iOS Settings."
)

How to modify a string

The following applies only to strings you modify that were already exported to the l10n repository AND to strings that needs new keys. If they weren't exported you can modify the value only (please check with the l10n team to confirm it wasn't exported). Please see below explanation about the key to see if this applies to you.

Modifying a string means we normally need to modify at least two parts of the MZLocalizedString, the key and the value. If you are changing a string such that its meaning has changed, you must update the key. If your changes are relevant only for English — for example, to correct a typographical error or to make capitalization consistent — then there is generally no need to update the key. There is a gray area between needing a new key or not. In some cases, it will be necessary to look at all the existing translations to determine if a new key would be beneficial. You should always reach out to the l10n team in case of doubt. Furthermore, the comment could also need to be adjusted, so please make ensure the comment still make sense following the string update.

Steps

When modifying a string with a new key, we need to make sure to keep the old version of that string alive until the version it was last used in is released on the App Store. If you don't change the key, then you don't need to create a new string in the struct. For changing the key follow these steps.

  1. Copy the MZLocalizedString modifying its key and value. You cannot modify the value only, since we need a new key for the string to be exported.
  2. Copy the old version of the string, delete it from this location, and paste it into the OldStrings struct (more info here). Because you've left the name the same in the previous place, Xcode shouldn't complain about missing strings.

Example

Here's an example of what the previously exemplified added strings would look like if we were to modify it.

extension String {
    struct OldStrings {
        struct v118 {
            public static let TurnOnNotificationsTitle = MZLocalizedString(
                key: "Settings.Notifications.TurnOnNotificationsTitle.v112",
                tableName: "Settings",
                value: "Turn on Notifications",
                comment: "This is the title informing the user needs to turn on notifications in iOS Settings.")
        }
    }
}
....
extension String {
    struct OriginalLocationStruct {
        public static let TurnOnNotificationsTitle = MZLocalizedString(
            key: "Settings.Notifications.TurnOnNotificationsTitle.v118",
            tableName: "Settings",
            value: "Turn on Notifications Feature",
            comment: "This is the title informing the user needs to turn on notifications feature in iOS Settings.")
    }
}

So the string OldStrings.v118.TurnOnNotifications is not used in our code anymore, but this string will still live in the l10n repository until we don't need it anymore. We will remove this unused string once the version 118 is released on the App Store.

How to remove a string

Similar as to how we modify strings, we need to keep strings that are removed in our project until the last version this string was used in gets released on the App Store.

Steps

  1. Add it to the OldStrings struct. More Info.

Example

extension String {
    struct OldStrings {
        struct v118 {
            public static let TurnOnNotificationsTitle = MZLocalizedString(
                key: "Settings.Notifications.TurnOnNotificationsTitle.v112",
                tableName: "Settings",
                value: "Turn on Notifications",
                comment: "This is the title informing the user needs to turn on notifications in iOS Settings.")
        }
    }
}

So the string TurnOnNotificationsTitle is not used in our code anymore, but this string will still live in the l10n repository until we don't need it anymore. We will remove this unused string once the version 118 is released on the App Store.

OldStrings struct

Removing or modifying strings requires that translations remain in the codebase/Pontoon for a certain amount of time. This can get confusing, so, to make things easy, the following rule should be followed:

  • When modifying or removing a string, the old version should be placed in the OldStrings struct, in a sub-struct corresponding to the version in which the removal is happening

So, if a string is being replaced in version 123, then the old string should go into struct v123. The old string would last be used in version 122, replaced in version 123, and deleted in version 125.

Deleting OldStrings sub-structs follows iOS support release pattern of n-2. So, if current release is v122, all sub-structs before v120 can be deleted from OldStrings.

String removal PR

If you followed the documentation above, you'll have noted that we don't remove strings entirely from the project until the version this string was last used in is released on the App Store. This means, once that particular release is made we need to create a PR which will remove the old unused string from our main branch. This PR is done manually for now once the tag is created for this release. Dot releases shouldn't have any effect on string removal. Here's an example of such PR.

Clone this wiki locally