DevOps/OpenStack

본격 OpenStack i18n CI 구조 분석 !

Sophie소피 2025. 10. 25. 17:31

OpenStack은 다양한 언어로 번역된 인터페이스를 제공하기 위해 i18n(internationalization) 시스템을 구축하고 있습니다.

이를 자동화하기 위해 Zuul이라는 CI/CD 시스템과 Ansible Playbook, 그리고 Zanata(번역 서버)를 함께 사용합니다.


Step 1. Zuul에서 작업 트리거: 번역 작업 시작점

Zuul은 OpenStack의 CI/CD 도구입니다.

프로젝트에 변화(eg. code merge)가 생기면 미리 정의된 작업들을 자동으로 실행합니다.

# 예: zuul.d/projects.yaml
- project:
    name: openstack/nova
    templates:
      - translation-jobs-master-only  # 번역 작업이 포함된 템플릿

translation-jobs-master-only 템플릿

  • 위치: zuul.d/project-templates.yaml
  • 하는 일: 번역 관련 작업을 master 브랜치에서만 실행
  • 포함된 job:
    • upstream-translation-update: pot 파일을 Zanata로 업로드 (post)
    • propose-translation-update: 번역된 po 파일을 저장소에 PR로 반영 (periodic - 매일 UTC 2시)
  • translation-jobs-master-only가 진짜 번역 자동화의 핵심 트리거 역할을 함
  • CI에서 번역까지 자동화한다는 게 처음에는 좀 생소했지만, 다국어 지원을 꾸준히 유지하려면 정말 필요한 구조라는 걸 이해함

Step 2. 번역 파일 동기화: pot ↔ po 자동화 흐름

 (1) upstream-translation-update

  • 실행 시점: code가 master에 merge된 직후
  • 역할:
    • 소스코드로부터 .pot 파일 생성
    • Zanata 번역 서버에 업로드
  • 관련 파일:
    • Ansible Playbook
    • 실제 수행 스크립트:
      • tools/handle_python_django_project
      • 내부에서 extract_messages, create-zanata-xml.py 등 호출
python3 create-zanata-xml.py \\
  -p horizon \\
  --srcdir . \\
  --txdir . \\
  -r '**/*.pot' \\
  '{path}/{locale_with_underscore}/LC_MESSAGES/{filename}.po' \\
  -e '.*/**' \\
  -f zanata.xml \\
  -v master

📝 처음엔 create-zanata-xml.py 옵션이 복잡해보이고 이해가 잘안갔지만,

결국 "어떤 소스 파일을 pot으로 만들고, 어떤 경로로 변환 결과를 저장할지 설정하는 도구"라는 걸 알게 됨.


(2) propose-translation-update

  • 실행 시점: 매일 정기적으로 (UTC 기준 2시)
  • 역할:
    • Zanata 서버에서 번역된 .po 파일을 Pull
    • 프로젝트 저장소로 PR 생성
  • 관련 파일:
    • Ansible Playbook
    • 실제 스크립트:
      • tools/pull_from_zanata
zanata-cli -B -e pull

실행 결과로, 프로젝트 내 locale/ 폴더 아래에 .po 번역 파일들이 자동으로 채워짐.

이때 필요한 구성

ini
# ~/.config/zanata.ini
[servers]
translate_openstack_org.url=https://translate.openstack.org/
translate_openstack_org.username=daeunhappyy
translate_openstack_org.key=SECRETKEY

처음엔 왜 직접 ini 파일을 만들어야 하지? 했는데,

CI에서 개인 권한이 아닌 서비스 계정으로도 설정할 수 있기 때문이라는 걸 나중에 이해함.

전체 흐름

[개발자가 문자열 추가]
      ↓
[Zuul post 단계: upstream-translation-update]
      ↓
[Zanata 서버에 .pot 파일 업데이트]
      ↓
[번역자들이 웹에서 번역 수행]
      ↓
[Zuul periodic: propose-translation-update]
      ↓
[Zanata에서 번역된 .po 파일 Pull → GitHub PR]

 

 

요소 설명

pot 파일 번역 대상 원문 문자열 모음 개발자가 작성한 메시지를 추출
po 파일 각 언어별 번역본 저장소 번역자는 이 파일을 수정
zanata-cli 번역 서버 CLI 툴 수동으로도 Pull/Push 가능하다는 걸 체험함
create-zanata-xml.py 번역 설정파일 생성 도구 zanata.xml이 있어야 CLI가 작동함
~/.config/zanata.ini 로그인 정보 없으면 인증 실패하고 아무 작업도 안 됨
upstream-translation-update pot → zanata 개발자 → 번역자 방향 흐름
propose-translation-update zanata → 저장소 번역자 → 프로젝트 방향 흐름
     

오픈스택 프로젝트 선택

  • 제가 선택한 프로젝트는 monasca-ui 입니다.
    • https://opendev.org/openstack/monasca-ui
    • → OpenStack의 모니터링 툴인 Monasca의 UI를 담당하는 프로젝트로, 번역과 문서화 외에도 모니터링 도메인에 대한 이해를 활용해보고싶습니다. (근데 3주 뒤에 retired project라고 하지말라고 이메일옴... 그러면 retired 리스트에 올려주지... 왜 안올려놔서.... ) 안녕 ~