sourcecode

NSLocalizedString을 사용하는 모범 사례

codebag 2023. 5. 13. 09:39
반응형

NSLocalizedString을 사용하는 모범 사례

(다른 사람들과 마찬가지로) 사용하고 있습니다.NSLocalizedString내 앱을 현지화합니다.

유감스럽게도 다음과 같은 몇 가지 "결함"(NSLocalizedString 자체의 결함은 아님)이 있습니다.

  • Xcode의 문자열에 대한 자동 완성 기능이 없습니다.이것은 작업을 오류 발생 가능성이 높을 뿐만 아니라 피곤하게 만듭니다.
  • 동일한 문자열이 이미 존재하는지 몰랐기 때문에 문자열을 재정의할 수 있습니다(예: "암호를 입력하십시오" 대 "암호를 먼저 입력하십시오").
  • 문제와 , 문자열을 "하여 붙여넣어야 않으면 "기억"/"기억"/"기억"이 필요합니다.genstring의 문자열에 개의 댓글을 .
  • 당신이 경우용을 사용하고 .genstring일부 문자열을 이미 현지화한 후에는 이전 현지화가 손실되지 않도록 주의해야 합니다.
  • 프로젝트 전체에 동일한 문자열이 흩어져 있습니다.예를 들어, 다음과 같이 사용한NSLocalizedString(@"Abort", @"Cancel action")모든 곳에서 코드 검토를 수행한 다음 문자열의 이름을 변경하도록 요청합니다.NSLocalizedString(@"Cancel", @"Cancel action")코드의 일관성을 높입니다.

제가 하는 일(그리고 SO에 대한 몇 가지 검색 후 많은 사람들이 이것을 한다는 것을 알게 되었습니다)은 별도의 것을 갖는 것입니다.strings.h내가 있는 곳에 줄을 서라.#define모든 로컬라이즈 코드.를 들어, .

// In strings.h
#define NSLS_COMMON_CANCEL NSLocalizedString(@"Cancel", nil)
// Somewhere else
NSLog(@"%@", NSLS_COMMON_CANCEL);

이것은 기본적으로 코드 완성, 변수 이름을 변경할 수 있는 단일 장소(더 이상 genstring이 필요하지 않음) 및 자동 리팩터를 위한 고유 키워드를 제공합니다.하지만, 이것은 결국 많은 사람들에게 대가를 치르게 됩니다.#defineLocString과 같이 본질적으로 구조화되지 않은 문.공통. 취소 등).

그래서, 이것이 어느 정도 잘 작동하지만, 저는 여러분들이 프로젝트에서 어떻게 하는지 궁금합니다.NSLocalizedString의 사용을 단순화하기 위한 다른 접근법이 있습니까?그것을 캡슐화하는 프레임워크가 있을까요?

NSLocalizedString몇 가지 제한 사항이 있지만, 코코아에서는 매우 중요하기 때문에 현지화를 처리하기 위해 사용자 지정 코드를 작성하는 것은 불합리합니다. 즉, 이 코드를 사용해야 합니다.다시 말해, 약간의 툴링이 도움이 될 수 있습니다. 제가 진행하는 방법은 다음과 같습니다.

문자열 파일 업데이트 중

genstrings문자열 파일을 덮어쓰고 이전 변환을 모두 삭제합니다.이전 문자열 파일을 구문 분석하기 위해 update_strings.py를 작성했습니다.genstrings기존 번역을 수동으로 복원할 필요가 없도록 빈칸을 채웁니다.스크립트는 기존 문자열 파일을 업데이트할 때 너무 큰 차이가 발생하지 않도록 가능한 한 가깝게 일치시킵니다.

문자열 이름 지정

사용하는 경우NSLocalizedString광고된 대로:

NSLocalizedString(@"Cancel or continue?", @"Cancel notice message when a download takes too long to proceed");

될 수 , 는 동일한 가 다른 수 입니다(" 드의다부동서문있될며수으정게코의다하니있수습자충다있때, " 동한영용가어른수컨가어텍다스", "돌할에문기트질에서의를미른일른분에일을열한▁you").OK그리고.Cancel 모듈별와 매우 정확한합니다.그렇기 때문에 모듈별 접두사와 매우 정확한 설명이 있는 의미 없는 all-caps 문자열을 항상 사용합니다.

NSLocalizedString(@"DOWNLOAD_CANCEL_OR_CONTINUE", @"Cancel notice window title when a download takes too long to proceed");

다른 위치에서 동일한 문자열 사용

동일한 문자열을 여러 번 사용하는 경우 매크로를 사용하거나 뷰 컨트롤러 또는 데이터 원본에서 인스턴스 변수로 캐시할 수 있습니다.이렇게 하면 동일한 현지화의 인스턴스 간에 오래되고 일관성이 없을 수 있는 설명을 반복할 필요가 없습니다. 이러한 설명은 항상 혼동을 일으킵니다.인스턴스 변수는 기호이므로 가장 일반적인 변환에서는 자동 완성을 사용할 수 있으며, 특정 변환에서는 "수동" 문자열을 사용할 수 있습니다. 이 문자열은 어차피 한 번만 발생합니다.

이 팁들로 코코아 현지화로 생산성이 향상되기를 바랍니다!

Xcode의 문자열 자동 완성에 대해서는 https://github.com/questbeat/Lin 을 사용해 볼 수 있습니다.

엔드프레드의 말에 동의하지만, 저는 이것을 추가하고 싶습니다.

두 번째 매개 변수는 ... 기본값으로 사용할 수 있습니다!!

(NSLocalizedStringWithDefaultValue는 genstring에서 제대로 작동하지 않으므로 이 솔루션을 제안했습니다.)

다음은 주석을 기본값으로 사용하는 NSLocalizedString을 사용하는 사용자 지정 구현입니다.

1. 사전 컴파일된 헤더(.pch 파일)에서 'NSLocalizedString' 매크로를 다시 정의합니다.

// cutom NSLocalizedString that use macro comment as default value
#import "LocalizationHandlerUtil.h"

#undef NSLocalizedString
#define NSLocalizedString(key,_comment) [[LocalizationHandlerUtil singleton] localizedString:key  comment:_comment]

로컬리제이션 처리기를 구현할 클래스 만들기

#import "LocalizationHandlerUtil.h"

@implementation LocalizationHandlerUtil

static LocalizationHandlerUtil * singleton = nil;

+ (LocalizationHandlerUtil *)singleton
{
    return singleton;
}

__attribute__((constructor))
static void staticInit_singleton()
{
    singleton = [[LocalizationHandlerUtil alloc] init];
}

- (NSString *)localizedString:(NSString *)key comment:(NSString *)comment
{
    // default localized string loading
    NSString * localizedString = [[NSBundle mainBundle] localizedStringForKey:key value:key table:nil];

    // if (value == key) and comment is not nil -> returns comment
    if([localizedString isEqualToString:key] && comment !=nil)
        return comment;

    return localizedString;
}

@end

사용하세요!

각 빌드에서 Localizable.strings 파일이 업데이트되도록 App 빌드 단계에서 실행 스크립트를 추가해야 합니다. 즉, Localized.strings 파일에 새로운 현지화된 문자열이 추가됩니다.

내 빌드 단계 스크립트는 셸 스크립트입니다.

Shell: /bin/sh
Shell script content: find . -name \*.m | xargs genstrings -o MyClassesFolder

코드에 이 새 줄을 추가하면 다음과 같습니다.

self.title = NSLocalizedString(@"view_settings_title", @"Settings");

그런 다음 빌드를 수행하면 ./Localizable.scripts 파일에 다음과 같은 새 행이 포함됩니다.

/* Settings */
"view_settings_title" = "view_settings_title";

그리고 'view_proxy_proxy'에 대한 키 == 값이 있으므로 사용자 지정 LocalizedStringHandler는 설명(예: 'Settings')을 반환합니다.

Voila :-)

Swift에서는 예를 들어 이 경우 "예" 버튼에 대해 다음을 사용합니다.

NSLocalizedString("btn_yes", value: "Yes", comment: "Yes button")

의 사용법을 기록합니다.value:기본 텍스트 값입니다.첫 번째 매개 변수는 변환 ID 역할을 합니다.value:매개 변수는 기본 텍스트를 나중에 변경할 수 있지만 변환 ID는 동일하게 유지된다는 것입니다.에는 Localizable.strings 파일이 됩니다."btn_yes" = "Yes";

에 약에만.value:매개 변수가 사용되지 않으면 첫 번째 매개 변수가 변환 ID와 기본 텍스트 값 모두에 사용됩니다.에는 Localizable.strings 파일이 됩니다."Yes" = "Yes";이런 종류의 현지화 파일 관리는 이상한 것 같습니다.특히 번역된 텍스트가 길면 ID도 길어요.기본 텍스트 값의 문자가 변경될 때마다 변환 ID도 변경됩니다.이로 인해 외부 번역 시스템을 사용할 때 문제가 발생합니다.번역 ID를 변경하는 것은 새로운 번역 텍스트를 추가하는 것으로 이해되며, 이는 항상 원하는 것은 아닙니다.

여러 언어로 Localizable.string을 유지 관리하는 데 도움이 되는 스크립트를 작성했습니다.자동 완성에는 도움이 되지 않지만 다음 명령을 사용하여 .strings 파일을 병합하는 데 도움이 됩니다.

merge_strings.rb ja.lproj/Localizable.strings en.lproj/Localizable.strings

자세한 내용은 https://github.com/hiroshi/merge_strings 를 참조하십시오.

도움이 되시는 분들도 계실 겁니다.

Swift 솔루션을 찾는 사람이 있다면요.제가 여기에 정리한 솔루션을 확인해 보십시오: Swifty Localization

설정하는 몇 가지 단계가 없어도 Google 스프레드시트(주석, 사용자 지정 색상, 강조 표시, 글꼴, 여러 시트 등)에서 매우 유연한 현지화를 수행할 수 있습니다.

간단히 말해서, 단계는 Google 스프레드시트 --> CSV 파일 --> Localizable.strings입니다.

또한 키 검색 및 디코딩에 대한 인터페이스 역할을 하는 구조인 Localizables.swift를 생성합니다(단, 키에서 String을 디코딩하는 방법은 수동으로 지정해야 합니다).

왜 이렇게 좋은 거죠?

  1. 더 이상 모든 플레이스에 일반 문자열로 키를 사용할 필요가 없습니다.
  2. 컴파일 시 잘못된 키가 검색됩니다.
  3. Xcode는 자동 완성을 수행할 수 있습니다.

지역화 가능한 키를 자동으로 완성할 수 있는 도구도 있습니다.실제 변수를 참조하면 항상 유효한 키가 됩니다. 그렇지 않으면 컴파일되지 않습니다.

// It's defined as computed static var, so it's up-to-date every time you call. 
// You can also have your custom retrieval method there.

button.setTitle(Localizables.login.button_title_login, forState: .Normal)

이 프로젝트는 Google App Script를 사용하여 Sheets --> CSV를 변환하고 Python 스크립트를 사용하여 CSV 파일을 변환합니다. --> Localizable.strings 이 예제 시트에서 무엇이 가능한지 간단히 확인할 수 있습니다.

iOS 7 및 Xcode 5에서는 'Localization.strings' 메서드를 사용하지 말고 새로운 'Base localization' 메서드를 사용해야 합니다.'기본 현지화'를 검색하면 몇 가지 튜토리얼이 있습니다.

Apple 문서: 기본 현지화

#define PBLocalizedString(key, val) \

[[NSBundle mainBundle] localizedStringForKey:(key) value:(val) table:nil]

저 자신도 .strings 파일에 항목을 넣는 것을 잊어버리고 코딩에 열중하는 경우가 많습니다.따라서 .strings 파일에 다시 넣고 번역해야 할 내용을 찾기 위한 도우미 스크립트가 있습니다.

NSLocalizedString을 통해 내 매크로를 사용하므로 NSLocalizedString의 두 번째 매개 변수로 nil이 사용되는 단순성을 위해 사용하기 전에 스크립트를 검토하고 업데이트하십시오.변경하고자 하는 부분은

NSLocalizedString\(@(".*?")\s*,\s*nil\) 

매크로 및 NSLocalizedString 사용과 일치하는 것으로 바꾸기만 하면 됩니다.

대본이 나옵니다. 3부만 있으면 됩니다.나머지는 모든 것이 어디에서 발생하는지 쉽게 확인하는 것입니다.

// Part 1. Get keys from one of the Localizable.strings
perl -ne 'print "$1\n" if /^\s*(".+")\s*=/' myapp/fr.lproj/Localizable.strings

// Part 2. Get keys from the source code
grep -n -h -Eo -r  'NSLocalizedString\(@(".*?")\s*,\s*nil\)' ./ | perl -ne 'print "$1\n" if /NSLocalizedString\(@(".+")\s*,\s*nil\)/'

// Part 3. Get Part 1 and 2 together.

comm -2 -3 <(grep -n -h -Eo -r  'NSLocalizedString\(@(".*?")\s*,\s*nil\)' ./ | perl -ne 'print "$1\n" if /NSLocalizedString\(@(".+")\s*,\s*nil\)/' | sort | uniq) <(perl -ne 'print "$1\n" if /^\s*(".+")\s*=/' myapp/fr.lproj/Localizable.strings | sort) | uniq >> fr-localization-delta.txt

출력 파일에는 Localizable.strings 파일에는 없지만 코드에서는 발견된 키가 포함되어 있습니다.다음은 샘플입니다.

"MPH"
"Map Direction"
"Max duration of a detailed recording, hours"
"Moving ..."
"My Track"
"New Trip"

물론 더 닦을 수 있지만, 공유하고 싶습니다.

언급URL : https://stackoverflow.com/questions/9895621/best-practice-using-nslocalizedstring

반응형