DADAHAE's Log
비싼 장난감 가지고 노는 중 (❁´▽`❁)*✲゚*
[WWDC22] 글로벌한 앱을 만드려면 어떻게 해야할까? Localization에 대해 알아보자. (Build global apps: Localization by example)
WWDC22 Build global apps: Localization by example
https://developer.apple.com/videos/play/wwdc2022/10110/
other reference: https://www.wwdcnotes.com/notes/wwdc22/10110/

 

 

 

 


 

 

지역화, 글로벌 앱을 만들기 위해서 꼭 필요한 부분입니다. 한국이 아니라 태평양을 넘어서 먼 나라의 사용자까지 노린다면 당연히 진행해야하는 스탭이죠. 

이렇게 중요한 지역화에 대해서 WWDC22의 영상을 보면서 알아보도록 하겠습니다. 날씨 앱으로 어떻게 지역화(Localization)를 적용하는지, 거기서 생기는 문제와 해결책들을 살펴보도록 하죠!

 

 

 

Translate, 번역

1. String의 localized

텍스트 번역은 String(localized:comment:)를 사용합니다. 이 메소드를 사용하면 Xcode가 번역해줍니다.

// In Swift code
let windPerceptionLabelText = String(
	localized: "Wind is making it feel cooler",
	comment: "Explains the wind is lowering the apparent temperature"
)

 

그런데 같은 단어여도 맥락에 따라 다르게 해석해야 하는 경우가 있다면, String(localized:defaultValue:comment)를 사용하면 됩니다. 이 메소드를 사용하면 영어에서는 같은 단어라도 각 언어권에 따라서 다른 번역을 해줄 수 있습니다.

// In Swift code
let filter = String(localized: "Archive.label",
					defaultValue: "Archive",
                    comment: "Name of the Archive folder in the sidebar")
                    
let filter = String(localized:"Archive .menuItem",
					defaultValue: "Archive",
                    comment: "Menu item title for moving the email into the Archive folder")

더 자세한 이야기는 WWDC21 Streamline your localized strings 영상을 참고하시면 좋습니다!

 

 

근데 이 메소드만 사용하면 뿅!! 하고 번역이 잘 될까요? (그러면 좋겠지만..) 당연히 아니겠죠.. 후

 

문자열안에 보간법을 쓰는 경우를 생각해보록 합시다. 각 언어마다 문법이 다르기 때문에 들어갈 단어와 문장이 이상하게 번역될 수도 있습니다. 영어와 독일어를 예를 들어서 살펴보도록 하져.

"Show weather in \(locationName)" 라는 문장은 영어로는 꽤 잘 출력됩니다. locationName은 변수이기 때문에 쿠퍼티노처럼 실제 지역명이 들어올 수도 있고, 나의 지역(my location)이 들어갈 수도 있습니다. 헉 여기서 문제가 생겨요

 

이 문장을 영어로 번역하면 크게 이상이 없지만, 독일어로 그대로 번역하면 우리가 원하는 뜻 번역되지 않습니다. (독일어를 정확히 모르지만, 문장에 들어갔을 때 문법이 차이가 나는 것 같다)

독일어의 경우 번역된 문장에서 전치사 inan으로 바꿔줘야 알맞은 문장이 됩니다. 번역하는 과정에서 전치사와 같은 문법이 잘못 해석될 수 있습니다. 

 

그러면 이 문제를 어떻게 해결할 수 있을까요... 애플은 늘 답을 알고 있습니다. 문자열을 2개로 쓰면 됩니다.

하나는 "진짜 지역 이름을 쓰는 문자열"로, 나머지 하나는 "나의 지역에 대한 문자열"로 2개의 문자열을 만드는 거죠.

특정 지역 이름을 보간법으로 넣을 경우, 지역 이름은 고유명사니까 매끄럽게 해석이 됩니다. 그러나 'my location'처럼 고유 명사가 아닌 값이 들어온다면, 이 문장만 따로 문자열을 작성해줍니다.

 

2. String의 comment

앞에서 보았듯이, String(localized:comment:)을 사용하여 텍스트를 번역할 수 있습니다. 근데 localized말고 comment라는 매개변수도 있네요? 이 친구의 역할은 무엇일까요?

 

바로 번역에 필요한 맥락을 작성하는 곳입니다. 번역을 하더라도, 앞 뒤의 맥락을 모른다면 이상하게 번역이 될 수 있습니다. 우리가 흔히 번역기에 돌리면 이상한 소리를 하는 경우가 보통 맥락이 맞지 않아서이죠.

그래서 Xcode의 번역기에게 번역할 문장에 대한 '맥락'을 comment에 담아서 같이 보내주는 겁니다. 그러면 번역이 더 매끄럽게 되겠죠??

 

당연히 정확한 맥락을 전달하기 위해서는 comment를 '잘' 작성해야 합니다. 잘 작성한 comment는 아래와 같은 조건을 가집니다.

  1. What interface element
  2. What context
  3. What each variable is

이 문장이 인터페이스의 어떤 요소인지, 어떤 맥락을 가지고 작성되었는지, 각 변수는 무엇인지 등... 번역을 위해 필요한 주변 정보를 작성해주면 됩니다. 그러면 Xcode의 번역기가 더 잘 이해하겠죠? 하하하

 

 

3. localized remote content

고정적인 텍스트말고, 서버에서 가져오는 데이터들은 어떻게 현지화할 수 있을까요?

 

날씨 앱에서 각 지역의 날씨 정보들이 서버에서 가져오는 데이터의 예시가 되겠네요. 나는 한국에 있으니 한국 날씨를, 미국사는 민지는 미국 날씨를 같은 날씨 앱으로 봐야하는데, 나와 민지는 서로 다른 위치에 있으므로 날씨 데이터도 현지화가 필요합니다.

 

원격으로 제어되는 컨텐츠(서버에서 받아오는 데이터)들에 대한 현지화는 서버에 사용자의 지역 정보를 보내줌으로서 해결될 수 있습니다.

어떻게 하냐구용?

 

서버에게 지원하는 언어(혹은 사용자의 지역, 국가) 정보를 보내줄 경우에 Bundle.preferredLocalizations(from: allServerLanguages).first로 사용자의 기기가 first로 지원하는 언어를 보내줍니다. 그러면 서버는 그 언어에 맞는 내용을 보내줄거에요!

 

나는 한국에 있으니 'kr'이 first가 되겠고, 이를 서버에 보내주게 됩니다. 그러면 서버는 한국(kr)에 맞는 날씨 정보를 찾아서 다시 앱으로 보내줄거에요. 나는 한국 날씨 정보를 받아서 앱에 보여주면, 짜잔- 현지화 완료입니다.

(이걸 위해서는 서버는 각 지역에 맞게 데이터를 보내줄 준비를 하고 있어야 합니다. 애플이 제공하는 날씨 API에서는 당연히 해줄 것이고, 개인적으로 서버를 구축한다면 이런 지역화에 대한 고려도 해야한다는 점, 잊지말긔)

 

4. pluralized texts

각 나라의 문법에는 복수형 규칙이 존재합니다. 1개일 때는 그냥 단수로 쓰다가 2개 이상의 물건이라면 s를 붙인다 뭐 그런거죠. 근데 이게 어떤 명사가 오느냐에 따라 달라지고, s냐 es냐 등등 디테일하게 변화합니다. 그리고 언어마다 문법도 달라서 이를 적용하기 까다롭습니다. 

 

이렇게 까다로운 복수형 규칙도 현지화가 가능한가요?

네넹. 가능합니다.

 

복수형 텍스트의 경우, Stringsdict 파일이나 automated grammar agreement(자동화된 문법 규칙)을 사용하세요.

(이 내용은 생각보다 어려워서 간단하게 짚고 넘어갔다. 언어권에 따라 필요한 복수형 규칙을 파일로 만들어서 사용할 수 있다는 의미로 이해했다)

String(localized: "\(amountOfRain) in last ^[\(numberOfHours) hour](inflect: true).",
       comment: "Label showing how much rain has fallen in the last number of hours")

 

 

Formatter, 형식자

1. 단위를 현지화하기 위한 Formatter

숫자가 어떤 포맷인지 formatter로 전달하면 단위 숫자를 현지화할 때 도움을 줄 수 있습니다.

let humidity = 54

// In a SwiftUI View
Text(humidity, format: .percent)

// In Swift code
humidity.formatted(.percent)

SwiftUI에서는 format을, 일반 Swift에서는 formatted를 사용하여 단위 숫자의 형식을 지정해줍니다. 이러면 뭐가 좋냐구요?

 

위 사진에 보다시피, 61%의 단위를 표현하는 방법은 나라마다 다를 수 있습니다. 그런데 이걸 그냥 일반 숫자로 표기하면 우리가 원하는 의미와 달라질 수 있겠죠? 

그렇기 때문에 단위 숫자의 형식, 포맷을 지정해주면 현지화를 하는 과정에서 그 지역에 맞게 바꿔줍니다.

 

쉬운 말로 하면 이런거에요. 일반 숫자로 단위를 표시하면, 번역하는 과정에서 그냥 '숫자'로 표기되고 '단위'의 의미가 사라질 수 있다는 겁니다. 그래서 '단위를 나타내는 숫자'의 형식을 지정해주는거죠. 그걸 해주는게 formatter인거고. 

 

formatter는 종류가 굉장히 많습니다. 그래서 이 영상에서 다 다루지 않고, WWDC20에서 발표한 Formatters: Make data human-friendly 의 영상을 살펴보면 더 자세히 알 수 있으니 필요하면 참고하세요!

 

 

2. 단위가 포함된 텍스트를 현지화 하는 방법

앞에서는 '단위 숫자'의 현지화에 대해서 이야기 했습니다. 그렇다면 이 '단위 숫자'를 하나의 텍스트에서 사용할 경우, 현지화하는데 문제가 없을까요? 자잘하게 안맞는 경우가 생길겁니다. (이것도 문법이나 기타 규칙들 때문입니다)

 

복수형 규칙과 formatter를 함께 사용하면 문제를 해결할 수 있습니다. 

이에 대한 예시로 강우량을 보여주는 텍스트를 현지화하는 함수를 만들어봅시다.

func expectedPrecipitationIn24Hours(for valueInMillimeters: Measurement<UnitLength>) -> String {
  // Use user's preferred measures
  let preferredUnit = UnitLength(forLocale: .current, usage: .rainfall)

  let valueInPreferredSystem = valueInMillimeters.converted(to: preferredUnit)

  // Format the amount of rainfall
  let formattedValue = valueInPreferredSystem
    .formatted(.measurement(width: .narrow, usage: .asProvided))

  let integerValue = Int(valueInPreferredSystem.value.rounded())

  // Load and use formatting string
  return String(localized: "EXPECTED_RAINFALL", 
         defaultValue: "\(integerValue) \(formattedValue) expected in next \(24)h.", 
          comment: "Label - How much precipitation (2nd formatted value, in mm or Inches) is expected in the next 24 hours (3rd, always 24).")
}

(여기도 꽤나 어려웠다 갑자기 왠 함수??? UnitLength랑 measure을 사용하라는데 뭔 소린지 모르겠다. 영상을 다시 보고 정리하자ㅜㅜ)

 

 

 

--(작성중)--

 

Swift Package의 현지화

앱 개발에 라이브러리를 사용하는 경우, Swift Package를 주로 사용할 것이다. 그러면 이 Swift Package는 어떻게 현지화를 할 수 있을까? 만약 내가 Swift Package 개발을 하고 있다면..

- 라이브러리를 만든 사람의 경우

- 라이브러리르 쓰는 사람의 경우

 

 

 

Layout and SwiftUI

현지화를 하다보면 문자열의 길이가 달라질 수 있다. 영어 문장을 한국어로 번역했을 때, 더 짧아지거나 길어질 수 있다는 뜻이다. 문자열의 길이 변화는 앱의 레이아웃에 영향을 미칠 수 있으므로 현지화의 과정에서 고려해야하는 점 중 하나이다.

 

- 언어에 따라 텍스트의 높이가 달라질 수 있다. (수직방향)

영어와 힌디어는 기본 텍스트 높이가 다르다. 그러면 날씨 앱에서 이를 어떻게 적용해서 보여줄까?

방법은 간단하다. 고정된 높이 값을 주지 않는 것이다. 레이아웃의 높이에 고정 값이 설정되어 있지 않으므로, 레이아웃 안에 있는 텍스트나 요소들의 높이에 따라 레이아웃(셀)의 높이 값이 결정된다. 

 

- 언어에 따라 텍스트의 길이가 달라질 수 있다. (수평방향)

SwiftUI에서 제공하는 Grid를 사용하면 쉽게 적용한다

 

* ViewThatFits: 뷰가 클리핑이 안맞으면 알아서 ui를 적절하게 변형해준다.

-> 사용자가 텍스트 크기를 키울 때에도 적용할 수 있는 부분이다.

 

 

 

  Comments,     Trackbacks