현지화

로케일 작업

CodeIgniter는 애플리케이션을 다양한 언어로 현지화하는 데 도움이 되는 여러 도구를 제공합니다. 애플리케이션의 전체 지역화는 복잡한 주제이지만 애플리케이션의 문자열을 지원되는 다른 언어로 바꾸는 것은 간단합니다.

로케일 구성

기본 로케일 설정

모든 사이트에는 운영되는 기본 언어/로캘이 있습니다. 이는 app/Config/App.php에서 설정할 수 있습니다:

<?php

namespace Config;

use CodeIgniter\Config\BaseConfig;

class App extends BaseConfig
{
    // ...

    public string $defaultLocale = 'en';

    // ...
}

값은 응용 프로그램이 텍스트 문자열 및 기타 형식을 관리하는 데 사용하는 모든 문자열이 될 수 있습니다. BCP 47 언어 코드를 사용하는 것이 좋습니다. 이로 인해 미국 영어의 경우 en-US, 프랑스어/프랑스의 경우 fr-FR과 같은 언어 코드가 생성됩니다. 이에 대한 더 읽기 쉬운 소개는 W3C’s site에서 찾을 수 있습니다.

시스템은 정확하게 일치하는 항목을 찾을 수 없는 경우 보다 일반적인 언어 코드로 대체할 만큼 똑똑합니다. 로케일 코드가 en-US로 설정되었고 en에 대해 설정된 언어 파일만 있는 경우 더 구체적인 en-US에 대한 것이 없기 때문에 해당 파일이 사용됩니다. 그러나 app/Language/en-US 디렉토리에 언어 디렉토리가 있는 경우 해당 디렉토리가 먼저 사용됩니다.

로케일 감지

중요

로케일 감지는 IncomingRequest 클래스를 사용하는 웹 기반 요청에 대해서만 작동합니다. 명령줄 요청에는 이러한 기능이 없습니다.

요청 중에 올바른 로케일을 감지하기 위해 지원되는 두 가지 방법이 있습니다.

  1. Content Negotiation: 첫 번째는 사용할 올바른 로케일을 결정하기 위해 자동으로 content negotiation을 수행하는 “설정하고 잊어버리는” 방법입니다.

  2. In Routes: 두 번째 방법을 사용하면 로케일을 설정하는 데 사용될 경로의 세그먼트를 지정할 수 있습니다.

로캘을 직접 설정해야 하는 경우 Setting the Current Locale을 참조하세요.

v4.4.0부터 Config\App::$supportedLocales 설정에서 설정된 유효한 로케일을 설정(및 재설정)하기 위해 IncomingRequest::setValidLocales()이 추가되었습니다.

콘텐츠 협상

app/Config/App.php에서 두 가지 추가 설정을 지정하여 자동으로 콘텐츠 협상이 이루어지도록 설정할 수 있습니다. 첫 번째 값은 Request 클래스에 우리가 로케일을 협상하고 싶다는 것을 알려주므로 간단히 true로 설정하십시오.

<?php

namespace Config;

use CodeIgniter\Config\BaseConfig;

class App extends BaseConfig
{
    // ...

    public bool $negotiateLocale = true;

    // ...
}

이 기능이 활성화되면 시스템은 $supportLocales에서 정의한 로케일 배열을 기반으로 올바른 언어를 자동으로 협상합니다. 지원하는 언어와 요청한 언어 간에 일치하는 항목이 없으면 $supportedLocales의 첫 번째 항목이 사용됩니다. 다음 예에서는 일치하는 항목이 없으면 en 로캘이 사용됩니다.

<?php

namespace Config;

use CodeIgniter\Config\BaseConfig;

class App extends BaseConfig
{
    // ...

    public array $supportedLocales = ['en', 'es', 'fr-FR'];

    // ...
}

경로 중

두 번째 방법은 사용자 정의 자리 표시자를 사용하여 원하는 로케일을 감지하고 요청에 설정합니다. 자리 표시자 {locale}은(는) 경로의 구간으로 배치될 수 있습니다. 있는 경우 일치하는 세그먼트의 내용이 귀하의 로캘이 됩니다.

$routes->get('{locale}/books', 'App\Books::index');

이 예에서 사용자가 http://example.com/fr/books,을(를) 방문하려고 하면 해당 로케일이 유효한 로케일로 구성되었다고 가정하여 로케일이 fr로 설정됩니다.

값이 app/Config/App.php$supportedLocales에 정의된 유효한 로케일과 일치하지 않는 경우 앱 구성 파일에 정의된 지원 로케일만 사용하도록 설정하지 않는 한 기본 로케일이 그 자리에서 사용됩니다.

$routes->useSupportedLocalesOnly(true);

참고

useSupportedLocalesOnly() 메소드는 v4.3.0부터 사용할 수 있습니다.

현재 로케일 설정

들어오는요청 로케일

로캘을 직접 설정하려면 IncomingRequest 클래스”에서 setLocale() 메서드를 사용할 수 있습니다.

/** @var \CodeIgniter\HTTP\IncomingRequest $request */
$request->setLocale('ja');

로케일을 설정하기 전에 유효한 로케일을 설정해야 합니다. 유효하지 않은 로케일을 설정하려고 하면 default locale이(가) 설정되기 때문입니다.

기본적으로 유효한 로케일은 app/Config/App.phpConfig\App::$supportedLocales에 정의되어 있습니다.

<?php

namespace Config;

use CodeIgniter\Config\BaseConfig;

class App extends BaseConfig
{
    // ...

    public array $supportedLocales = ['en', 'es', 'fr-FR'];

    // ...
}

참고

v4.4.0부터 유효한 로케일을 설정(및 재설정)하기 위해 IncomingRequest::setValidLocales()이 추가되었습니다. 유효한 로케일을 동적으로 변경하려면 이를 사용하십시오.

언어 로케일

lang() 함수에 사용된 Language 클래스에도 현재 로케일이 있습니다. 인스턴스화하는 동안 IncomingRequest 로케일로 설정됩니다.

언어 클래스를 인스턴스화한 후 로캘을 변경하려면 Language::setLocale() 메서드를 사용하세요.

/** @var \CodeIgniter\Language\Language $lang */
$lang = service('language');
$lang->setLocale('ja');

현재 로케일 검색

현재 로케일은 항상 getLocale() 메소드를 통해 IncomingRequest 객체에서 검색할 수 있습니다. 컨트롤러가 CodeIgniter\Controller을 확장하는 경우 $this->request을 통해 사용할 수 있습니다.

<?php

namespace App\Controllers;

class UserController extends BaseController
{
    public function index()
    {
        $locale = $this->request->getLocale();
    }
}

또는 Services class을 사용하여 현재 요청을 검색할 수 있습니다.

$locale = service('request')->getLocale();

언어 현지화

언어 파일 생성

언어 문자열은 지원되는 각 언어(로케일)에 대한 하위 디렉터리와 함께 app/Language 디렉터리에 저장됩니다.

app/
    Language/
        en/
            App.php
        fr/
            App.php

참고

언어 파일에는 네임스페이스가 없습니다.

언어에는 필요한 특정 명명 규칙이 없습니다. 파일 이름은 파일에 포함된 콘텐츠 유형을 설명하기 위해 논리적으로 지정되어야 합니다. 예를 들어, 오류 메시지가 포함된 파일을 생성한다고 가정해 보겠습니다. 간단히 이름을 Errors.php로 지정할 수도 있습니다.

파일 내에서 배열의 각 요소에 언어 키가 있고 반환할 문자열이 있을 수 있는 배열을 반환합니다.

<?php

return [
    'languageKey' => 'The actual message to be shown.',
];

참고

언어 키의 시작과 끝 부분에는 점(.)을 사용할 수 없습니다.

또한 중첩 정의도 지원합니다.

<?php

return [
    'languageKey' => [
        'nested' => [
            'key' => 'The actual message to be shown.',
        ],
    ],
];
<?php

return [
    'errorEmailMissing'    => 'You must submit an email address',
    'errorURLMissing'      => 'You must submit a URL',
    'errorUsernameMissing' => 'You must submit a username',
    'nested'               => [
        'error' => [
            'message' => 'A specific error message',
        ],
    ],
];

기본 사용법

lang() 도우미 함수를 사용하면 파일 이름과 언어 키를 마침표(.)로 구분하여 첫 번째 매개변수로 전달하여 모든 언어 파일에서 텍스트를 검색할 수 있습니다.

예를 들어 Errors.php 언어 파일에서 errorEmailMissing 문자열을 로드하려면 다음을 수행합니다.

echo lang('Errors.errorEmailMissing');

중첩된 정의의 경우 다음을 수행합니다.

echo lang('Errors.nested.error.message');

요청된 언어 키가 현재 로케일(Language Fallback 이후)에 대한 파일에 없으면 문자열이 변경되지 않고 다시 전달됩니다. 이 예에서는 존재하지 않는 경우 Errors.errorEmailMissing 또는 Errors.nested.error.message을 반환합니다.

매개변수 바꾸기

참고

다음 기능이 모두 작동하려면 시스템에 intl 확장 프로그램을 로드해야 합니다. 확장이 로드되지 않으면 교체가 시도되지 않습니다. 훌륭한 개요는 Sitepoint에서 확인할 수 있습니다.

언어 문자열의 자리 표시자를 대체하기 위해 값 배열을 lang() 함수의 두 번째 매개변수로 전달할 수 있습니다. 이를 통해 매우 간단한 숫자 변환 및 형식 지정이 가능합니다.

<?php

// The language file, Tests.php:
return [
    'apples'      => 'I have {0, number} apples.',
    'men'         => 'The top {1, number} men out-performed the remaining {0, number}',
    'namedApples' => 'I have {number_apples, number, integer} apples.',
];

// Displays "I have 3 apples."
echo lang('Tests.apples', [3]);

자리 표시자의 첫 번째 항목은 숫자인 경우 배열 항목의 인덱스에 해당합니다.

// Displays "The top 23 men out-performed the remaining 20"
echo lang('Tests.men', [20, 23]);

원하는 경우 명명된 키를 사용하여 작업을 보다 쉽게 ​​수행할 수도 있습니다.

// Displays "I have 3 apples."
echo lang('Tests.namedApples', ['number_apples' => 3]);

분명히 숫자 교체 이상의 작업을 수행할 수 있습니다. 기본 라이브러리의 official ICU docs에 따라 다음 유형의 데이터를 대체할 수 있습니다.

  • 숫자 - 정수, 통화, 퍼센트

  • 날짜 - 단기, 중기, 장기, 전체

  • 시간 - 짧음, 중간, 길음, 전체

  • 철자법 - 숫자를 철자합니다(즉, 34는 34가 됩니다).

  • 서수

  • 지속

다음은 몇 가지 예입니다.

<?php

// The language file, Tests.php
return [
    'shortTime'  => 'The time is now {0, time, short}.',
    'mediumTime' => 'The time is now {0, time, medium}.',
    'longTime'   => 'The time is now {0, time, long}.',
    'fullTime'   => 'The time is now {0, time, full}.',
    'shortDate'  => 'The date is now {0, date, short}.',
    'mediumDate' => 'The date is now {0, date, medium}.',
    'longDate'   => 'The date is now {0, date, long}.',
    'fullDate'   => 'The date is now {0, date, full}.',
    'spelledOut' => '34 is {0, spellout}',
    'ordinal'    => 'The ordinal is {0, ordinal}',
    'duration'   => 'It has been {0, duration}',
];

// Displays "The time is now 11:18 PM"
echo lang('Tests.shortTime', [time()]);
// Displays "The time is now 11:18:50 PM"
echo lang('Tests.mediumTime', [time()]);
// Displays "The time is now 11:19:09 PM CDT"
echo lang('Tests.longTime', [time()]);
// Displays "The time is now 11:19:26 PM Central Daylight Time"
echo lang('Tests.fullTime', [time()]);

// Displays "The date is now 8/14/16"
echo lang('Tests.shortDate', [time()]);
// Displays "The date is now Aug 14, 2016"
echo lang('Tests.mediumDate', [time()]);
// Displays "The date is now August 14, 2016"
echo lang('Tests.longDate', [time()]);
// Displays "The date is now Sunday, August 14, 2016"
echo lang('Tests.fullDate', [time()]);

// Displays "34 is thirty-four"
echo lang('Tests.spelledOut', [34]);

// Displays "It has been 408,676:24:35"
echo lang('Tests.ordinal', [time()]);

조건부 대체, 복수화 수행 등과 같은 기능이 무엇인지 더 잘 이해하려면 MessageFormatter 클래스와 기본 ICU 형식을 읽어야 합니다. 이전에 제공된 두 링크 모두 사용 가능한 옵션에 대한 훌륭한 아이디어를 제공합니다.

로케일 지정

매개변수를 교체할 때 사용할 다른 로케일을 지정하려면 해당 로케일을 lang() 함수의 세 번째 매개변수로 전달할 수 있습니다.

<?php

// Displays "The time is now 23:21:28 GMT-5"
echo lang('Test.longTime', [time()], 'ru-RU');

// Displays "£7.41"
echo lang('{price, number, currency}', ['price' => 7.41], 'en-GB');
// Displays "$7.41"
echo lang('{price, number, currency}', ['price' => 7.41], 'en-US');

현재 로캘을 변경하려면 Language Locale을 참조하세요.

중첩 배열

언어 파일을 사용하면 중첩 배열을 사용하여 목록 등을 더 쉽게 작업할 수 있습니다.

<?php

// Language/en/Fruit.php

return [
    'list' => [
        'Apples',
        'Bananas',
        'Grapes',
        'Lemons',
        'Oranges',
        'Strawberries',
    ],
];

// Displays "Apples, Bananas, Grapes, Lemons, Oranges, Strawberries"
echo implode(', ', lang('Fruit.list'));

언어 대체

특정 로케일(예: Language/en/App.php)에 대한 메시지 세트가 있는 경우 해당 로케일에 대한 언어 변형을 각각 자체 폴더(예: Language/en-US/App.php)에 추가할 수 있습니다.

해당 로케일 변형에 대해 다르게 지역화되는 메시지에 대한 값만 제공하면 됩니다. 누락된 메시지 정의는 기본 로캘 설정에서 자동으로 가져옵니다.

더 좋아졌습니다. 새 메시지가 프레임워크에 추가되었지만 아직 해당 로케일에 맞게 번역할 기회가 없었던 경우 현지화가 영어(en)로 돌아갈 수 있습니다.

따라서 로케일 fr-CA을 사용하는 경우 먼저 Language/fr-CA 디렉토리에서 지역화된 메시지를 찾은 다음 Language/fr 디렉토리, 마지막으로 Language/en 디렉토리에서 찾습니다.

시스템 메시지 번역

own repository에는 시스템 메시지 번역의 “공식” 세트가 있습니다.

해당 저장소를 다운로드하고 Language 폴더를 app 폴더에 복사할 수 있습니다. App 네임스페이스가 폴더에 매핑되므로 통합된 번역이 자동으로 선택됩니다.

또는 프로젝트 내에서 다음 명령을 실행하는 것이 더 나은 방법입니다.

composer require codeigniter4/translations

번역 폴더가 적절하게 매핑되므로 번역된 메시지가 자동으로 선택됩니다.

시스템 메시지 번역 재정의

프레임워크는 System Message Translations을 제공하며, 설치한 패키지도 메시지 번역을 제공할 수 있습니다.

일부 언어 메시지를 재정의하려면 app/Language 디렉터리에 언어 파일을 생성하세요. 그런 다음 파일에서 재정의하려는 배열만 반환합니다.

명령을 통해 번역 파일 생성

Added in version 4.5.0.

app 폴더에서 번역 파일을 자동으로 생성하고 업데이트할 수 있습니다. 이 명령은 lang() 함수의 사용을 검색하고 Config\App에서 로케일 defaultLocale``을 정의하여 ``app/Language의 현재 번역 키를 결합합니다. 수술 후에는 언어 키를 직접 번역해야 합니다. 이 명령은 일반적으로 File.array.nested.text 중첩된 키를 인식할 수 있습니다. 이전에 저장된 키는 변경되지 않습니다.

php spark lang:find
<?php

// Controllers/Translation/Lang.php
$message  = lang('Text.info.success');
$message2 = lang('Text.paragraph');

// The following will be saved in Language/en/Text.php
return [
    'info' => [
        'success' => 'Text.info.success',
    ],
    'paragraph' => 'Text.paragraph',
];

참고

명령이 폴더를 검색할 때 app/Language는 건너뜁니다.

생성된 언어 파일은 코딩 표준을 따르지 않을 가능성이 높습니다. 포맷하는 것이 좋습니다. 예를 들어 php-cs-fixer이 설치된 경우 vendor/bin/php-cs-fixer fix ./app/Language을 실행합니다.

업데이트하기 전에 다음 명령으로 찾은 번역을 미리 볼 수 있습니다.

php spark lang:find --verbose --show-new

--verbose의 자세한 출력에는 잘못된 키 목록도 표시됩니다. 예를 들어:

...

Files found: 10
New translates found: 30
Bad translates found: 5
+------------------------+---------------------------------+
| Bad Key                | Filepath                        |
+------------------------+---------------------------------+
| ..invalid_nested_key.. | app/Controllers/Translation.php |
| .invalid_key           | app/Controllers/Translation.php |
| TranslationBad         | app/Controllers/Translation.php |
| TranslationBad.        | app/Controllers/Translation.php |
| TranslationBad...      | app/Controllers/Translation.php |
+------------------------+---------------------------------+

All operations done!

보다 정확한 검색을 위해 검색하려는 로캘이나 디렉터리를 지정하세요.

php spark lang:find --dir Controllers/Translation --locale en --show-new

자세한 정보는 다음 명령을 실행하여 확인할 수 있습니다.

php spark lang:find --help

명령을 통한 동기화 번역 파일

Added in version 4.6.0.

현재 언어에 대한 번역을 마친 후 다른 언어에 대한 파일을 만들어야 할 수도 있습니다. 이를 해결하기 위해 Spark lang:find 명령을 사용할 수 있습니다. 그러나 모든 번역, 특히 lang('App.status.' . $key, ['payload' => 'John'], 'en')과 같이 동적으로 설정된 매개변수가 있는 번역을 감지하지 못할 수도 있습니다.

번역이 누락되지 않도록 하려면 완성된 언어 파일을 복사하여 수동으로 번역하는 것이 가장 좋습니다. 이 접근 방식은 명령이 간과했을 수 있는 고유 키를 보존합니다.

당신이 해야 할 일은 다음을 실행하는 것 뿐입니다:

// Specify the locale for new/updated translations
php spark lang:sync --target ru

// or set the original locale
php spark lang:sync --locale en --target ru

결과적으로 번역 키가 포함된 파일을 받게 됩니다. 대상 로케일에 중복된 키가 있으면 저장됩니다.

경고

새 번역에서 일치하지 않는 키가 삭제됩니다!