To rename a String Catalog key in Xcode, preserve the source message separately, update its code references, and verify every existing translation and variant. For extracted strings, Xcode 26 offers a conversion refactor; changing only a lookup key is insufficient.

This guide is for someone maintaining a SwiftUI Mac app with an existing .xcstrings catalog. The task is to replace message-shaped keys with meaningful identifiers while keeping the displayed wording and translations intact. Apple documents the APIs and conversion workflow below, but does not promise that an arbitrary key edit automatically transfers every translation.

What must stay unchanged when a key changes?

A localizable message has more than an identifier. Apple describes its key, default value, comment, and string table as separate components. The key identifies the message at runtime; the default value supplies source wording. A catalog holds a table’s translations and metadata. Treat a rename as a coordinated change to that message contract. Discover String Catalogs

Before editing, record the following for each affected entry. These synthetic examples illustrate a rename; they are not measured results.

Component Before Intended result
Lookup key Open collection collection.open
Source message Open collection Unchanged
Table Localizable Unchanged
Bundle Main app bundle Unchanged
Translator context Button opening the selected collection Preserved
Existing translations Current values in every localization Preserved
Count arguments, if present Integer count Same type and meaning
Plural or device variants Existing branches Preserved

Use this record as a comparison aid. A successful build alone cannot establish that the translations survived: the app may still display a default message when a lookup misses. SwiftUI documents that a localized key can display directly when no catalog match exists. With a semantic key, that can expose an identifier such as collection.open in the interface. Preparing views for localization

Find the source before editing the catalog

Open the existing catalog in Xcode’s Project navigator. Choose Editor > Assistant, then select the entry to inspect its source. Apple also documents the arrow beside a key and example usages in the Attributes inspector as ways to locate references. For extracted strings, choose Product > Build after source changes to synchronize the catalog. Localizing and varying text with a string catalog

Check whether the entry is extracted from code or managed manually. Apple explains that source code governs extracted messages: builds synchronize their source values. A translated entry that disappears from extraction remains as Stale; an untranslated one can be removed. Manually managed entries are not updated or removed by extraction. Therefore, do not delete an old translated entry merely because a replacement has appeared. Discover String Catalogs

Create a recoverable checkpoint before proceeding, and compare the affected entry against it afterward. Keep the table and bundle unchanged during this task so that a missing translation has fewer possible causes. Apple’s localization APIs accept table and bundle information precisely because these determine where a message is found. Preparing your app’s text for translation

Use Xcode’s conversion refactor for extracted strings

For a project using Xcode 26 or later, consider converting the existing extracted entry to a generated localizable symbol. Apple introduced this workflow in Xcode 26 and demonstrates changing a key to a semantic name during conversion. This is a documented route for changing how a message is identified and referenced together. Code-along: Explore localization with Xcode

  1. In build settings, check that Generate String Catalog Symbols is set to Yes if the existing project needs it enabled.
  2. In the catalog editor, select the existing key, Control-click it, and choose Refactor > Convert Strings to Symbols.
  3. Inspect the preview showing the catalog key change and affected source locations.
  4. Edit the proposed semantic name and, where applicable, argument names in the conversion interface.
  5. Compare the current and modified code using the highlighted preview, then click Convert.
  6. Build and compare the resulting entry with your checkpoint, including translations and variants.

Apple documents these conversion controls and shows generated usage examples in the Attributes inspector. Use those examples instead of guessing a Swift identifier from punctuation in your desired catalog key. Generated symbols depend on catalog information, and nondefault tables introduce a table namespace. Using generated localizable symbols in your code

This refactor is specifically a transition from extracted strings to generated symbols. The cited documentation does not establish a universal rename operation for every manually managed entry or every external reference. If the preview omits a required reference, account for it explicitly before removing the previous key.

Keep extraction if you prefer keys and defaults in code

You can also retain code-driven extraction. Apple explicitly supports separate lookup keys and source messages through String(localized:defaultValue:...): the first argument supplies the key, and defaultValue supplies the source string. For example, a semantic key can retain Open collection as its default message. Preparing your app’s text for translation

The following complete app source demonstrates that pattern with one static label and one integer count. Use a macOS SwiftUI app target with a deployment target of macOS 12 or later, and replace its existing app entry source rather than adding a second @main declaration. Add Localizable.xcstrings to the app target. The example was inspected against Apple’s APIs; it was not compiled here because a Swift toolchain was unavailable.

import Foundation
import SwiftUI

@main
struct CatalogRenameDemoApp: App {
    var body: some Scene {
        WindowGroup {
            CatalogRenameDemoView()
        }
    }
}

struct CatalogRenameDemoView: View {
    private let itemCount: Int = 7

    var body: some View {
        VStack(alignment: .leading, spacing: 12) {
            Text(verbatim: String(
                localized: "collection.open",
                defaultValue: "Open collection",
                comment: "Label for opening the selected collection."
            ))

            Text(verbatim: String(
                localized: "collection.itemCount",
                defaultValue: "\(itemCount) items",
                comment: "Number of items in the selected collection."
            ))
        }
        .padding()
    }
}

Here, String(localized:...) resolves the localized text before the resulting string is displayed. Text(verbatim:) makes that display step explicit. Apple distinguishes immediate string localization from LocalizedStringResource, which represents a lookup that can be deferred. For reusable interfaces that pass unresolved messages between views, Apple recommends a localizable type such as LocalizedStringResource. LocalizedStringResource, Preparing your app’s text for translation

When migrating an existing message using this approach, build to create or update the destination entry, then transfer the existing translations before deleting the previous entry. Apple documents entering translations directly by selecting a localization and editing the corresponding language column. For a varied message, preserve each relevant branch rather than copying only its top-level text. This staged transfer is a practical migration procedure derived from the documented editing tools, not an automatic rename guarantee. Localizing and varying text with a string catalog

How do extraction and runtime formatting differ?

Extraction happens during development: Xcode discovers supported localizable expressions and updates the catalog. Runtime formatting happens when the app resolves the message and inserts values. The sample count 7 is a runtime argument; it should not become part of the stable key.

Keep the integer interpolation inside the localizable expression. Apple’s String.LocalizationValue supports interpolation and directs developers who want arbitrary identifiers to initializers with a static key and separate defaultValue. Constructing an ordinary rendered string first is not equivalent to preserving that localizable message and its arguments. String.LocalizationValue

For grammatical count messages, select the extracted count entry, Control-click, and choose Vary by Plural. Complete the source variants and each existing localization’s required variants. For an English source, Apple illustrates One with %lld item and Other with %lld items. Merely adding interpolation does not finish those variants. Localizing and varying text with a string catalog

During a rename, preserve argument types, positions, and meanings. If the old message contains an integer count, replacing it with a preformatted string also changes the formatting contract. For generated symbols, Xcode creates functions with typed parameters for messages containing format specifiers; inspect those signatures when converting. Using generated localizable symbols in your code

Verify preservation before removing the old entry

Use the following checks as a completion test. They separate a catalog problem from a lookup or formatting problem.

Check Expected result Investigate if it fails
Source wording Matches the checkpoint Missing or altered default value
Existing translations Every previous value remains available under the new key Incomplete transfer or wrong destination
Variant structure All previous plural and device branches remain Only a top-level value was copied
Runtime label Displays the intended message Key, table, bundle, or localization mismatch
Synthetic counts 0, 1, 7 Values insert correctly and required plural branches work Argument or variant mismatch
Old references No required use remains Incomplete migration

To test the Mac app in an existing localization, choose Product > Scheme > Edit Scheme, select Run, open Options, and choose an App Language. Close the dialog and run the Mac destination. Repeat for the localizations affected by the rename, checking the actual label and count message. Apple documents this scheme-based testing workflow. Testing localizations when running your app

If the new key appears but its translation is empty, return to the previous entry and transfer the missing content. If the identifier appears onscreen, inspect the lookup inputs. If only counts fail, inspect interpolation and variants. Remove the old entry after its content has been accounted for and its required references have moved. The finished change should alter the identifier while preserving the message, its arguments, and the translations readers already receive.

Sources