프레임워크가 소유한 패널이 있는 Mac 앱에서는 두 수준에서 대체 동작을 정의하세요. 각 번들이 선택하는 언어와 조회에 실패했을 때 각 메시지가 반환하는 값입니다. 개발용 현지화 언어를 영어로 설정하고, 직접 관리하는 메시지에는 명시적인 영어 기본값을 사용하세요.
이 가이드에서는 앱이 소유한 Workspace 레이블과 프레임워크가 소유한 Panel ready 레이블이 있는 간단한 데스크톱 윈도우에 이 규칙을 적용합니다. 레이블은 예시용입니다. 언어나 번역이 누락되어도 메시지를 읽을 수 있도록 유지하면서, 번역이 있으면 일반적인 현지화 동작을 보존하는 것이 목적입니다.
대체 동작 규칙은 무엇을 보장해야 할까요?
앱과 프레임워크가 소유한 메시지에 다음 규칙을 적용하세요. 시스템의 언어 일치 규칙에 따라 선택된 사용 가능한 현지화를 사용하고, 선호 언어와 일치하는 현지화가 없으면 영어를 개발용 현지화로 사용하며, 문자열 조회에 실패하면 해당 메시지의 명시적인 영어 기본값을 반환합니다. 각 메시지에는 소유 번들과 문자열 테이블을 지정해야 합니다.
언어 선택은 사용자의 선호 언어와 사용 가능한 현지화를 고려합니다. 첫 번째로 선호하는 언어가 없더라도 영어가 즉시 표시된다는 뜻은 아닙니다. 다른 선호 언어가 먼저 일치할 수 있습니다. Apple의 보관된 번들 가이드에서는 이 선택 순서와 선호 언어가 일치하지 않을 때 개발용 현지화를 사용하는 방식을 설명합니다. 현재 문서에서는 CFBundleDevelopmentRegion을 번들의 대체 언어 식별자로 정의합니다. 번들 콘텐츠에 접근하기, CFBundleDevelopmentRegion.
기대 결과를 정의할 때는 다음 결정 표를 사용하세요. 모든 번역 누락을 같은 상황으로 취급하지 않고, 리소스 선택과 메시지 조회를 구분합니다.
| 조건 | 직접 관리하는 메시지에 대한 규칙 | 확인할 항목 |
|---|---|---|
| 선호 언어에 사용 가능한 번역이 있음 | 해당 번역 표시 | 번들, 테이블, 키 |
| 첫 번째 선호 언어는 사용할 수 없지만 다른 선호 언어가 일치함 | 시스템 언어 일치 규칙이 사용 가능한 현지화를 선택하도록 함 | 선호 순서와 포함된 리소스 |
| 선호 현지화와 일치하는 항목이 없음 | 번들의 영어 개발용 리소스 사용 | 개발 언어와 영어 리소스 |
| 선택된 조회에서 메시지를 찾을 수 없음 | 해당 메시지의 명시적인 영어 기본값 반환 | 메시지의 defaultValue |
| 프레임워크 조회가 실수로 앱 번들을 대상으로 함 | 번들 인수 수정 | 리소스 소유권 |
| 번역은 있지만 문구가 부적절함 | 번역 수정 | 카탈로그 콘텐츠와 검토 |
이 표는 Apple의 리소스 선택 규칙과 Swift 이니셜라이저에 문서화된 기본값 동작을 결합합니다. 이는 해당 API에서 도출한 구현 정책이지, String Catalogs에 별도의 대체 기능이 있는 것은 아닙니다. 조회가 성공했지만 문구가 부적절한 경우는 기본값 사용을 위해 이니셜라이저가 문서화한 조건인 조회 실패에 해당하지 않습니다. String.init(localized:defaultValue:table:bundle:locale:comment:).
소유 대상마다 영어 원본 리소스 구성하기
이 예시에서는 최신 Xcode, macOS 13 이상을 대상으로 하는 macOS SwiftUI 앱, 그리고 PanelKit이라는 이름의 임베디드 동적 Swift 프레임워크 대상을 사용합니다. 프레임워크를 앱에 연결하고 임베드하세요. 이는 예시 프로젝트의 사전 요구 사항이며, 프레임워크 이름은 기존 제품을 가리키지 않습니다.
두 대상 모두 영어를 개발 언어로 설정하고, 빌드된 각 번들의 CFBundleDevelopmentRegion이 en로 확인되는지 검증하세요. 두 대상에 각각 해당하는 영어 원본 리소스를 제공하세요. 개발 언어 식별자는 대체 언어를 설명할 뿐, 누락된 메시지 콘텐츠를 제공하지 않습니다. Apple은 en을 영어 언어 식별자로 문서화합니다. CFBundleDevelopmentRegion.
각 대상에 별도의 Localizable.xcstrings 카탈로그를 만드세요. Xcode에서 File > New > File from Template을 선택하고 String Catalog를 고른 다음, 이름을 Localizable로 지정합니다. 한 카탈로그는 앱 대상에, 다른 카탈로그는 프레임워크 대상에 할당하세요. 리소스 소유권을 분리하면 각 조회를 독립적으로 검증할 수 있습니다. Apple은 카탈로그 생성 절차를 문서화하며 여러 카탈로그를 지원합니다. 문자열 카탈로그로 텍스트 현지화 및 변형하기.
아래 코드를 추가한 후 Product > Build를 선택하세요. Xcode는 인식된 현지화 호출을 카탈로그로 추출합니다. workspace.title이 앱 카탈로그에, panel.ready이 프레임워크 카탈로그에 표시되고, 의도한 영어 원본 값이 들어 있는지 확인하세요. 카탈로그 사이드바의 추가 버튼을 사용해 지원 언어를 추가하고 관련 메시지의 번역을 입력합니다. 문자열 카탈로그로 텍스트 현지화 및 변형하기.
카탈로그의 완성도와 런타임 조회의 정확성은 별도로 확인해야 합니다. 프레임워크 카탈로그에 번역 항목이 있어도 앱 번들을 검색하는 호출에는 도움이 되지 않습니다. Apple은 메인 번들 외부에서 문자열을 불러오는 코드는 해당 대상과 연결된 번들을 전달해야 한다고 명시합니다. 앱 텍스트를 번역에 맞게 준비하기.
각 메시지에 번들, 키, 테이블, 기본값 지정하기
안정적인 예시용 키와 알아보기 쉬운 영어 기본값을 사용하세요. defaultValue을 받는 Swift 이니셜라이저는 표시되는 원본 텍스트와 다른 키를 지원합니다. 번들에서 현지화된 문자열을 조회하지 못하면 기본값이 반환됩니다. table 매개변수는 문자열 테이블을 선택하며, 생략하면 Localizable이 선택됩니다. String.init(localized:defaultValue:table:bundle:locale:comment:).
프레임워크 메시지를 프레임워크에 두기
이 전체 Swift 소스 파일을 동적 PanelKit 프레임워크 대상에 추가하세요. 표식 클래스는 해당 대상에 정의되어 있으므로 Bundle(for:)이 해당 번들을 가리킵니다. Apple은 이 클래스 기반 접근 방식을 현재의 #bundle 매크로를 대신하는 방법으로 문서화합니다. 앱 텍스트를 번역에 맞게 준비하기.
import Foundation
private final class PanelBundleAnchor: NSObject {}
public enum PanelText {
public static var resourceBundle: Bundle {
Bundle(for: PanelBundleAnchor.self)
}
public static var ready: String {
String(
localized: "panel.ready",
defaultValue: "Panel ready",
table: "Localizable",
bundle: resourceBundle,
comment: "Status label above the framework panel."
)
}
}
프레임워크는 String을 앱에 반환하기 전에 메시지를 조회합니다. 이로써 명확한 소유권 경계가 정해집니다. 키, 원본 텍스트, 테이블, 리소스 번들은 프레임워크가 관리하고, 앱은 최종 표시 문자열을 받습니다.
앱 메시지와 프레임워크 메시지를 함께 표시하기
생성된 앱 진입점 파일을 이 완성된 예시로 바꾸세요. 연결된 프레임워크 모듈의 이름은 PanelKit이고 앞의 파일을 포함한다고 가정합니다. 앱 대상에는 앱 진입점이 하나만 남아 있어야 합니다.
import Foundation
import SwiftUI
import PanelKit
@main
struct FallbackDemoApp: App {
var body: some Scene {
WindowGroup {
VStack(alignment: .leading, spacing: 12) {
Text(verbatim: String(
localized: "workspace.title",
defaultValue: "Workspace",
table: "Localizable",
bundle: .main,
comment: "Heading for the main workspace."
))
Text(verbatim: PanelText.ready)
}
.padding(24)
}
}
}
앱 조회는 .main을 명시적으로 사용하고, 프레임워크 조회는 프레임워크 자체 리소스 번들을 사용합니다. 둘 다 영어 기본값을 제공합니다. 이는 Apple이 문서화한 번들 선택 및 기본값 매개변수를 따릅니다. 대상 구성이 완전하게 설정되었는지 확인하려면 Xcode에서 프로젝트를 빌드하고 실행하세요. 이 예시들은 여기서 실행되지 않았습니다. String.init(localized:defaultValue:table:bundle:locale:comment:).
기존 구현에서 Bundle.localizedString(forKey:value:table:)를 사용한다면, 누락된 키에 대해 읽기 쉬운 결과가 필요할 때 읽기 쉬운 비어 있지 않은 value을 지정하세요. Apple 문서에 따르면 value이 없거나 비어 있으면 누락된 키 자체를 반환하고, 비어 있지 않으면 value를 반환합니다. 따라서 panel.ready과 같은 키를 그대로 노출하면 메시지 규칙에 어긋나는 경우 명시적인 대체값이 필요합니다. localizedString(forKey:value:table:).
프레임워크가 다른 언어를 선택할 수 있는지 결정하기
올바른 번들을 전달하면 검색 위치가 정해집니다. 혼합 현지화 설정은 현지화 선택과 포함 앱의 관계에 영향을 줍니다. Apple은 프레임워크에서 현지화된 문자열을 가져올 때 사용하는 불리언 CFBundleAllowMixedLocalizations를 Localized resources can be mixed로 표시합니다. CFBundleAllowMixedLocalizations.
Swift Forums의 동작 설명에 따르면 앱의 Info.plist에서 이 키를 활성화하면 다른 번들이 메인 앱에서 지원하지 않는 현지화도 선택할 수 있습니다. 이 설정을 켜지 않으면 메인 번들이 해당 번들의 선택을 제한합니다. 이는 오래된 설명 토론이지만 Apple의 최신 키 참조 문서와 함께 참고할 수 있습니다. Swift 패키지 매니저 현지화.
예시 윈도우에서는 앱과 프레임워크가 지원하는 언어를 일치시키고 두 곳 모두에 영어 개발용 리소스를 두는 방식을 권장합니다. 초기 규칙에서는 프레임워크가 독립적으로 언어를 선택하도록 하지 마세요. 프레임워크에서 추가 번역을 사용하게 하려는 경우에는 앱의 CFBundleAllowMixedLocalizations 불리언을 YES로 설정하고 해당 구성을 명시적으로 테스트하세요. Swift 패키지 매니저 현지화.
이 키를 활성화해도 번역이나 누락된 메시지의 기본값이 제공되지는 않습니다. 이러한 책임은 여전히 리소스 파일과 조회 호출에 있습니다. 마찬가지로 직접 작성한 호출에 지정하는 기본값은 그 호출의 조회 실패 결과를 정할 뿐, 모든 시스템 컨트롤이나 프레임워크 메시지에 적용되는 보편적인 영어 대체 동작을 설정하지 않습니다.
이 String 이니셜라이저의 locale 인수를 번역 언어를 바꾸는 용도로 사용하지 마세요. Apple 문서에 따르면 이 인수는 숫자와 같은 보간 값의 현지화 방식을 제어하며, 현지화 문자열을 조회할 때 사용하는 로캘은 바꾸지 않습니다. 이 작업에는 지원되는 언어 구성과 테스트 제어 기능을 사용하세요. String.init(localized:defaultValue:table:bundle:locale:comment:).
언어 누락과 메시지 누락을 따로 테스트하기
Product > Scheme > Edit Scheme에서 현지화 검사를 실행하세요. Run을 선택하고 Options를 연 다음 App Language를 선택합니다. 대화상자를 닫고 Mac 앱을 다시 실행하세요. Apple은 시스템 전체 설정을 바꾸지 않고 현지화를 시험하는 방법으로 이 절차를 문서화합니다. 언어만의 문제를 조사할 때는 지역 설정을 그대로 두세요. 앱 실행 시 현지화 테스트하기.
다음 테스트 매트릭스를 프로젝트별 진단 자료로 활용하세요. 번들 라우팅 검사에서는 지원되는 원본 언어가 아닌 현지화에 App translation sample과 Framework translation sample처럼 서로 다른 영어 테스트 표식을 임시로 사용하세요. 이는 진단용 콘텐츠이지 번역이나 언어 식별자가 아닙니다.
- 원본 동작을 확인합니다. 영어를 선택해 실행합니다.
Workspace와Panel ready가 표시되어야 합니다. - 번역 리소스 라우팅을 확인합니다. 지원되는 테스트 현지화를 선택합니다. 두 소유 카탈로그의 서로 다른 표식이 표시되어야 합니다.
- 누락된 메시지의 기본값을 확인합니다. 폐기할 테스트 수정본에서 프레임워크 조회 키를
panel.ready.probe로 바꾸고defaultValue는 그대로 둡니다. 해당 프로브 항목이 테스트 카탈로그에 포함되지 않게 합니다. 조회에 실패하면Panel ready가 표시되어야 합니다. 그 뒤 원래 키를 복구합니다. - 지원하지 않는 언어 선택을 확인합니다. 지원되는 언어가 하나도 없는 선호 언어 목록을 시험합니다. 소유 번들 두 곳 모두 영어 개발용 리소스를 사용하는지 확인합니다. 지원되지 않는 언어가 첫 번째 선호 언어이고 뒤이어 지원되는 언어가 오는 경우도 테스트하세요. 이 경우에는 기대 결과가 다릅니다.
- 혼합 현지화를 활성화한 경우 확인합니다. 프레임워크에만 제공되는 언어를 시험합니다. 의도한 동작을 기록하고 앱의 혼합 현지화 설정이 이에 부합하는지 테스트합니다.
세 번째 검사는 조회 실패를, 네 번째 검사는 언어 일치를 각각 분리해 확인합니다. 번역되지 않은 카탈로그 행만 테스트하면 결과 리소스 구성이 조회에도 영향을 주므로 두 조건이 혼동될 수 있습니다. 누락된 키의 기대 결과는 Swift 이니셜라이저에 따르고, 선호 언어 선택은 번들 규칙에 따릅니다. String.init(localized:defaultValue:table:bundle:locale:comment:), 번들 콘텐츠에 접근하기.
결과가 예상과 다르면 실제 소유 번들을 살펴보세요. developmentLocalization은 CFBundleDevelopmentRegion에 해당하는 값을 보고하고, preferredLocalizations는 언어 선호도에 따라 정렬된 사용 가능한 현지화를 보고합니다. Bundle.main과 PanelText.resourceBundle에서 이 속성들을 비교하세요. 구성 진단에는 도움이 되지만, 각 조회의 최종 확인은 실제 표시 메시지로 해야 합니다. developmentLocalization, preferredLocalizations.
유용한 대체 동작 규칙은 각 결과를 설명할 수 있게 합니다. 선택된 언어는 번들 일치 규칙에 따라 정해지고, 메시지는 소유 테이블에서 가져오며, 조회 실패 시 읽기 쉬운 명시적 기본값이 반환됩니다. 직접 관리하는 앱 및 프레임워크 메시지마다 이 규칙을 적용하고, 사용자가 메시지를 접하는 데스크톱 윈도우에서 함께 검증하세요.
출처
- 앱 텍스트를 번역에 맞게 준비하기 — Apple
- 문자열 카탈로그로 텍스트 현지화 및 변형하기 — Apple
- CFBundleDevelopmentRegion — Apple
- String.init(localized:defaultValue:table:bundle:locale:comment:) — Apple
- localizedString(forKey:value:table:) — Apple
- CFBundleAllowMixedLocalizations — Apple
- Swift 패키지 매니저 현지화 — Swift Forums
- 앱 실행 시 현지화 테스트하기 — Apple
- developmentLocalization — Apple
- preferredLocalizations — Apple
- 번들 콘텐츠에 접근하기 — Apple Documentation Archive