📑 0. Discover String Catalogs
Xcode 15가 모든 문자열을 한 곳에서 관리하며 로컬라이제이션을 쉽게 만들어주는지 알아봅시다. String Catalogs를 활용해 프로젝트에서 어떻게 추출, 편집, 내보내기, 빌드를 하는지 보여줍니다. 또한 기존 프로젝트에서 마이그레이션하는 방법도 공유합니다.
기존 Localization 방법

- 이전에는 로컬라이제이션하려면 STRINGS와 STRINGDICT 파일을 가지고 있어야 했다.
- 모든 문자열을 수동으로 동기화해야하고, 그러다보면 놓칠 수도 있다.
새로운 Localization 방법, String Catalogs

- 이제 새로운 파일 String Catalog가 이 두 파일을 대신한다.
- 모든 문자열을 한 곳에서 쉽게 관리할 수 있으며, 콘텐츠가 완전히 현지화되어 있음을 알 수 있다.
String Catalog

- String Catalog의 문자열은 Xcode에 의해 자동으로 추출된다.
- 직접 문자열들을 추가할 필요 없다.
문자열 내에 변수 추가하기

- 뒷마당에 방문한 실제 새의 수를 표현하기 위해, 이 수를 나타내는 변수를 추가했다.

- 카탈로그로 돌아가 보면 새로운 문자열이 추가되었다.
- 그리고 번역 비율이 98%로 내려갔다.
String Catalog의 편집 기능
- 예를들어 문자열에 'tap'이라는 단어가 있지만, Mac 디바이스에서 올바른 단어를 사용하고 싶을 때,
- 영어 문자열로 돌아가서 '탭하여 자세히 알아보기'라는 문자열을 찾는다.

- 오른쪽 버튼으로 클릭하고, Mac을 선택해 텍스트를 올바르게 조정한다.

- 실행 대상을 Mac으로 변경하고 해보면 확인할 수 있습니다.
문자열을 추출할 수 있는 위치부터(Extract),
카탈로그와 상호 작용하기 위한 Xcode 에디터(Edit),
Localization을 내보내는 방법을 알아보겠습니다(Export).
그리고 카탈로그가 빌드되는 방식(Build)과
기존 프로젝트에서 카탈로그를 적용하는 방법(Migration)을 알아봅시다.
📌 Extract
Localizable strings은 런타임에 사용자에게 표시되는 텍스트 문자열이므로
앱에서 지원하는 모든 언어로 번역해야 한다.
Lacalizable Strings의 4가지 구성 요소

1. Key
- String의 고유 식별자이고, 문자열 자체와 동일할 수 있다.
2. Default Value
- 원하는 경우 명시적으로 지정할 수 있고, 지정하지 않으면 기본 Key로 되돌아간다.

Xcode 14.3에는 프로젝트 에디터를 사용해 프로젝트의 기본 현지화를 변경하는 기능이 도입되었다.
이 기능은 소스 코드의 문자열이 영어가 아닌 경우에 유용하다.
3. 문자열 주석(Comment)
- 번역가에게 문자열이 어디서 어떻게 사용되고 있는지에 대한 맥락을 제공하는 방법입니다.
4. Table
- 각각의 Localizable strings는 하나 이상의 파일에 해당하는 String Table에 속한다.
- 기본적으로 코드의 문자열은 'Localizable' 테이블에 배치된다.
- 문자열을 다른 방식으로 구성하려는 경우에는 직접 지정할 수 있습니다.
(이오 says, Localizable.xcstrings가 아닌 WWDCNotifications.xcstrings라는 새로운 파일을 생성하고 적용할 수 있어요!)

- 기존의 방식인 .strings를 사용하던 경우, 각 언어의 lproj 내에 있는 .strings, .stringsdict 파일이 포함되어 있다. 그리고 각각의 언어로 나뉘어져 있다.
- 하지만 카탈로그는 단일 파일에 전체 문자열을 테이블을 포함한다. 이 안에 각 문자열에 대한 번역과 메타데이터가 모두 포함된다.

- 여러 문자열 table로 정리하고 싶다면, 여러 카탈로그를 생성할 수 있다.
- Key는 각 테이블 내에서는 고유하지만, 테이블 간에 고유할 필요는 없다.
- 예를 들어, "Welcome to WWDC!" 라는 문자열은 앱 내에 다른 상황에서 표시될 수 있기 때문에 두 파일에 모두 존재할 수 있다.
Lacalizable strings를 어디서 찾을 수 있을까?

- Xcode 15는 String Catalog를 자동으로 채우고 프로젝트에서 발견한 Localizable String과 동기화하려고 할 것이다.
- Xcode는 소스 코드, 인터페이스 빌더 파일, Info.plist 파일에서 문자열을 찾아 포함시킬 수 있다.
1. SwiftUI

- SwiftUI는 문자열을 지정할 때마다 자동으로 Localization 대상으로 간주한다.
- 모든 문자열은 Localization 대상이 되고, Localizable.xcstrings라는 카탈로그로 추출된다.
- LocalizedStringKey 타입을 받는 모든 매개변수에 대해 적용된다.
- Text에서도 comment, table 등을 지정할 수 있다.

- Localization을 위해 LocalizedStringResource를 사용하도록 권장되고, 이 타입은 리터럴뿐만아니라 comment, table, key와 다른 default value를 지정할 수 있다.
2. Swift

- String을 사용하거나 AttributedString의 localized 파라미터가 포함된 init을 사용하면 인식한다.
- Foundation을 import한 곳은 LocalizedStringResource를 직접 사용할 수도 있다.

- String Catalogs는 Localizable strings를 추출하기 위해 Swift 컴파일러를 활용한다.
- 그래서 빌드 설정에서 Use Compiler to Extract Swift String를 활성화해야 한다.
2. Objective-C

- Objective-C에서는 NSLocalizedString을 사용할 수 있다.
3. C

- C에서는 CFCopyLocalizedString을 사용할 수 있다.
사용자 정의 Localizable strings macro를 지정

- Localized String Macro Names 빌드 설정을 사용하면 된다.
4. Interface Builder

- Interface Builder에서는 자동으로 Localization 대상이 된다.
- 인스펙터를 활용하면, Comment도 지정할 수 있다.
- 카탈로그가 Storyboard나 xib와 연동되면, 인터페이스 빌더에서 Localizable strings가 모두 카탈로그에 포함된다.
- 소스 코드와 마찬가지로 빌드할 때마다 카탈로그를 업데이트한다.
5. Info.plist

- Info.plist 파일에서도 작동한다.
- InfoPlist.xcstrings 파일을 프로젝트에 추가하면 된다.
- 빌드할 때마다 Xcode는 알려진 Localizable Info.plist Key들을 카탈로그에 추가한다.
- 수동으로도 추가할 수 있다.
6. App Shortcut

- App Shortcut에서도 가능한데, "Spotlight your app with App Shortcuts" 영상을 참고하면 된다.
어떻게 카탈로그에 반영될까?
- 빌드할 때마다 Xcode는 현재 스킴과 플랫폼에서 Localizable strings를 찾는다.
- 코드에서 새로운 문자열을 발견하면 카탈로그에 추가한다.
- 문자열이 삭제되었을 때, 아직 번역되지 않은 문자열은 Xcode가 알아서 삭제한다.
- 하지만 이미 번역된 문자열은 그대로 두고 'Stale' 이라는 상태로 표시한다.
- 더이상 해당 문자열을 소스코드에서 찾을 수 없다는 내용이다.

- 수동으로도 문자열을 관리할 수 있다.
- 수동으로 관리되는 문자열은 Xcode가 업데이트하거나 제거하지 않는다.
📌 Edit
Localization 상태

1. New - 아직 번역되지 않은 문자열이다. 새 문자열을 코드에 추가하면 나타난다.
2. Needs Review - 검토가 필요하다는 의미다. 그대로 현재 값을 쓰려면 'Mark as Reviewed'를 선택하면 된다.
3. 초록색 체크 - 추가 작업 필요 없음
복수형 처리
- 앞에서 Backyard Birds에 추가한 문자열은 최근 방문자 수를 표시한다.
- 영어에서는 숫자가 1인 경우와 아닌 경우에 따라 문법을 변경해야 한다.

- 우크라이나어와 같은 언어에서는 고려해야 할 경우의 수가 더 많을 수 있다.
- 그래서 전달되는 숫자에 따라 문자열을 다양하게 표현할 수 있는 방법이 필요하다.
stringdict로 복수형 표현하기 (old)

- 이전에는 stringsdict 파일이 필요했다. 이는 사용하기 어려운 작업이 있다.
catalog로 복수형 표현하기 (new)

- 카탈로그는 문자열 변형을 위한 워크플로우를 직접 제공한다.
- 메뉴를 열면 변형할 수 있는 다양한 옵션들이 표시된다.
Substitutions
- 런타임에는 복잡한 여러 상황이 발생할 수 있다. 한 문장에서도 여러 변수가 들어가는 경우가 있을 수 있다.
- 카탈로그에서는 substitutions를 활용한다.
- 문자열 안에 있는 두 개의 인자 모두를 복수형으로 변형하면, @ 기호로 시작하는 각 subtitution은 복수형 경우와 그 값을 담은 dictionary를 저장한다.

- substitution은 string interpolation을 사용해 전달된다. 인스펙터에서는 위치와 C스타일 포맷 정보를 표시한다.
📌 Export

- 번역가와 함께 작업해야 하는 경우가 있다.
- Xcode는 Export Localizations 옵션을 제공한다.
XLIFF

- Xcode 10에서 소개된 Localization Catalog는 프로젝트나 워크스페이스 내의 모든 Localizable Contents를 담은 패키지 형식이다.
- 모든 Localizable strings와 그 번역이 포함된 XLIFF 파일을 살펴보자.
- XLIFF는 현지화 데이터를 저장하고 전달하기 위한 표준 형식이다.
.stringsdict 파일에 정의된 복수형 문자열의 XLIFF 표현
// Stringsdict in XLIFF
<trans-unit id="/%lld Recent Visitors:dict/NSStringLocalizedFormatKey:dict/:string">
<source>%#@recentVisitors@</source>
<target>%#@recentVisitors@</target>
</trans-unit>
<trans-unit id="/%lld Recent Visitors:dict/recentVisitors:dict/one:dict/:string">
<source>%lld Recent Visitor</source>
<target>%lld Visitante Recente</target>
</trans-unit>
<trans-unit id="/%lld Recent Visitors:dict/recentVisitors:dict/other:dict/:string">
<source>%lld Recent Visitors</source>
<target>%lld Visitantes Recentes</target>
</trans-unit>
- 이렇게 trans-unit이 stringdict 형식으로 들어가는 경로 역할을 한다.
String Catalog에서 온 XLIFF
// String Catalog in XLIFF
<trans-unit id="%lld Recent Visitors|==|plural.one">
<source>%lld Recent Visitor</source>
<target>%lld Visitante Recente</target>
</trans-unit>
<trans-unit id="%lld Recent Visitors|==|plural.other">
<source>%lld Recent Visitors</source>
<target>%lld Visitantes Recentes</target>
</trans-unit>

- 문자열 Key, 구분자 시퀀스, 점(.)으로 구분되어 표현한다.
- 복수형, 디바이스 지정, subtitution 등을 표현할 수 있다.
- 자동화 도구가 읽기 쉬울 뿐만아니라, 사람이 이해하기에도 쉽도록 설계되었다.
- 현재 변형되지 않은 문자열도 XLIFF에서 직접 변형하고, 가져와서 변경할 수 있다.

- XLIFF가 export할 때 String Catalog 형식을 사용하려면, Localization Prefers String Catalogs를 "Yes"로 설정한다.
- 번역가로부터 번역된 카탈로그를 받아 다시 import할 수 있다.
- String Catalog에서 가져온 문자열은 자동으로 추가된다.

- Edit Scheme에서 앱 언어를 변경하고 앱을 실행해서 확인할 수 있다.
📌 Build

내부적으로 JSON 파일 형식을 사용하기 때문에, 소스 코드로 변경사항을 비교하기 쉽다.
빌드하면 이 파일들이 .strings와 .stringdict 파일로 컴파일된다.
이 파일들은 오랜 기간 운영체제에서 지원되어 왔기 때문에, 최소 배포 버전을 업데이트하지 않아도 카탈로그를 사용할 수 있다.
코드에서 추출된 문자열은 최종 빌드에 포함되지 않는다. 런타임에 표시되는 문자열에 영향이 없고, 디스크 공간을 절약할 수 있다.
📌 Migrate
어떤 문자열 파일과 대상을 마이그레이션할지 선택할 수 있다.
파일을 오른쪽 클릭해서 "Migrate to String Catalog"를 선택한다.
Xcode에는 프로젝트 내에 마이그레이션 가능한 모든 파일을 나열하는 내장 어시스턴트가 있다.
마이그레이션이 완료되면, Xcode는 문자열을 추출하기 위해 빌드를 한다.
빌드 후 Catalog를 확인하면, strings 파일의 모든 문자열과 stringsdict 파일의 모든 복수형 문자열이 마이그레이션 되어있다.
일부 진행률이 100%가 아님을 확인할 수 있는데, 이는 프로젝트 내 현지화되지 않은 문자열을 찾는데 도움을 준다.

Swift 패키지에서도 패키지 매니페스트에 현지화를 추가하고, Swift 5.9를 사용하고 있는지 확인한다.
기본 테이블 이름 "Localizable"로 새 String Catalog를 패키지에 추가한다.
프로젝트를 빌드하면 패키지의 모든 문자열을 확인할 수 있다.
새 프로젝트나 패키지의 Localization을 시작하는 것은 어렵지 않다.
Swift Catalog는 프로젝트 내 번역 관리를 단순화해준다.
기존 문자열을 마이그레이션하여 현지화를 시작해보거나,
앱을 한 번도 현지화해본 적이 없다면 얼마나 쉽게 시작할 수 있는지 볼 수 있다.
Discover String Catalogs - WWDC23 - Videos - Apple Developer
Discover how Xcode 15 makes it easy to localize your app by managing all of your strings in one place. We'll show you how to extract,...
developer.apple.com