창작마당

G7 게시글 번역 관리 플러그인 - Glitter Translate

Glitter Gim 2026.09.25 14:18 조회수:221
#플러그인

GnuBoard7 게시글의 제목과 본문 번역을 언어별로 관리하고, 현재 언어와 게시글 권한에 맞게 제공하는 플러그인.

Name       : G7 게시글 번역 관리 플러그인 - Glitter Translate
Plugin ID  : glitter-translate
Namespace  : GlitterTranslate
Version    : 0.2.16
Vendor     : Glitter.kr
Author     : Glitter.kr
License    : MIT
Target     : GnuBoard7
Dependency : sirsoft-board >= 1.1.2

Glitter Translate는 제품명 및 영문명이며, 공개 문서와 배포 화면에서는 G7 게시글 번역 관리 플러그인 - Glitter Translate를 정식 표시 이름으로 사용합니다.


개요

glitter-translate은 GnuBoard7(G7) 환경에서 sirsoft-board 게시글의

제목과 본문을 여러 언어로 관리하고, 현재 locale과 게시글 읽기 권한에

맞는 번역 결과를 제공하는 독립 번역 플러그인입니다.

단순히 번역문을 별도로 저장하는 데서 끝나지 않고, 원문과 번역문의 상태를

비교하여 현재 사용할 수 있는 번역인지 판단하고, 번역이 없거나 원문

변경으로 오래된 번역이 된 경우에는 안전하게 원문으로 fallback합니다.

또한 개별 게시글을 위한 Single Resolver와 목록 화면을 위한 Batch

Resolver를 제공하여 User Template이나 다른 G7 확장이 Glitter Translate의

database 구조를 직접 알지 않고도 동일한 번역 결과를 재사용할 수 있도록

구성했습니다.

주요 범위는 다음과 같습니다.

  •   sirsoft-board Post 제목(title) 번역

  •   sirsoft-board Post 본문(content) 번역

  •   관리자 수동 번역 관리

  •   원문 hash 기반 stale 감지

  •   현재 locale 기준 번역 resolution

  •   번역 없음 / stale 상태의 원문 fallback

  •   게시글 읽기 권한을 따르는 Single Resolver

  •   최대 100개 Post를 처리하는 Batch Resolver

  •   Template / Module / Plugin에서 재사용 가능한 번역 API

  •   원본 Post와 번역 데이터의 저장 책임 분리

이 기능을 하나의 독립적인 translation provider 계층으로 연결합니다.


sirsoft-board Post

        ↓

Original title / content

        ↓

Glitter Translate

        ├─ Translation Storage

        ├─ Source Hash

        ├─ Permission Check

        └─ Locale Resolver

                ↓

        Translation Result

          ├─ current → 번역

          ├─ missing → 원문

          └─ stale   → 원문

                ↓

Template / Module / Plugin

현재 버전은 v0.2.16입니다.

v0.2.14~v0.2.16에서는 번역 데이터 자체뿐 아니라 **본문의 표현 방식(content representation)**까지 Resolver와 renderer 사이에서 일관되게 전달하도록 확장했습니다. 특히 원본이 HTML이어도 번역문이 plain text라면 번역문은 text mode로 표시되어 줄바꿈이 유지되며, v0.2.16에서는 standalone URL에 대한 progressive link preview도 지원합니다.


주요 기능

게시글 제목 / 본문 번역

현재 번역 대상으로 지원하는 resource는 다음과 같습니다.


Resource : sirsoft-board.post

Fields

├─ title

└─ content

원본 게시글의 title과 content를 다국어 구조로 변경하지 않습니다.

Glitter Translate가 별도의 번역 저장소를 소유하고 원본 Post와 연결하여

사용합니다.


sirsoft-board

└─ Original Post

   ├─ title

   └─ content

glitter-translate

└─ Translation

   ├─ resource_type

   ├─ resource_id

   ├─ locale

   ├─ field

   ├─ value

   └─ source_hash

따라서 번역 기능을 사용하기 위해 기존 g7_board_posts 구조를 변경하지

않습니다.


수동 번역 관리

Glitter Translate 0.2.16은 자동 번역 서비스가 아니라 **수동 번역 관리와

안정적인 번역 resolution**에 초점을 둡니다.

관리자 화면에서는 게시판과 게시글을 선택한 뒤 locale별 번역을 관리할 수

있습니다.

주요 관리 흐름은 다음과 같습니다.


Board 선택

    ↓

Post 선택

    ↓

원문 확인

    ↓

Locale 선택

    ↓

제목 / 본문 번역 입력

    ↓

번역 저장

관리 화면에서는 원본 제목과 본문을 확인하면서 번역을 작성할 수 있으며,

제목과 본문의 상태는 각각 독립적으로 판단됩니다.

지원 상태는 다음과 같습니다.


current

missing

stale

관리자 UI에서는 locale 단위의 번역 저장 / 번역 삭제 흐름을

제공하면서 내부 API는 제목과 본문을 독립된 field 단위로 관리합니다.


Source Hash와 Stale 감지

번역을 저장할 때 해당 시점의 원문을 기준으로 SHA-256 source hash를

기록합니다.

이후 원문이 변경되면 현재 원문의 hash와 저장된 source_hash가

달라지므로 기존 번역을 stale 상태로 판단할 수 있습니다.


Original Post

      ↓

SHA-256

      ↓

source_hash

      ↓

Translation 저장

조회 시에는 다음과 같이 판단합니다.


현재 원문 hash

      +

저장된 source_hash

      ↓

같음

  → current

      ↓

번역 사용

다름

  → stale

      ↓

원문 fallback

stale 여부를 확인하기 위해 원문이나 번역 데이터를 읽는 과정에서 자동으로

수정하거나 삭제하지 않습니다.

즉, **원문이 변경되었다는 이유만으로 기존 번역 데이터를 파괴하지

않으면서 오래된 번역이 사용자에게 그대로 노출되는 것은 방지**합니다.


Locale-aware Fallback

Glitter Translate는 별도의 브라우저 locale 체계를 만들지 않고

GnuBoard7의 현재 request locale을 사용합니다.

개념적인 resolution은 다음과 같습니다.


현재 G7 Locale

      ↓

Translation 조회

      ↓

┌─────────┬─────────┬─────────┐

│ current │ missing │  stale  │

└────┬────┴────┬────┴────┬────┘

     ↓         ↓         ↓

   번역       원문       원문

따라서 번역 플러그인을 사용하는 Template이 자체적인 언어 상태를 별도로

유지할 필요가 없습니다.


Permission-aware Resolution

번역 데이터가 존재한다는 사실 자체가 사용자가 읽을 수 없는 게시글의

존재를 노출해서는 안 됩니다.

Glitter Translate의 public resolver는 sirsoft-board의 기존 게시글 읽기

권한 경계를 재사용합니다.


Resolver Request

      ↓

Board 확인

      ↓

Post Read Permission

      ↓

읽을 수 있는 Post만 확정

      ↓

Translation Resolution

권한이 없는 Post는 번역 데이터가 존재하더라도 public resolver 결과를

통해 존재 여부가 노출되지 않도록 처리합니다.

Glitter Translate가 별도의 게시글 공개 권한 체계를 만들지 않는 것이 기본

원칙입니다.


Single Resolver

하나의 게시글에 대한 번역을 조회할 수 있습니다.


GET /api/plugins/glitter-translate/posts/{slug}/{postId}/translations

주로 다음과 같은 화면에 적합합니다.

  •   게시글 상세 화면

  •   문서 Reader

  •   단일 콘텐츠 View

  •   개별 Post를 사용하는 Template component

흐름은 다음과 같습니다.


Post

 ↓

Single Resolver

 ↓

Permission

 ↓

Locale

 ↓

title / content

 ↓

current translation

또는 original fallback

Batch Resolver

목록 화면에서 여러 Post의 번역을 한 번에 조회할 수 있도록 Batch

Resolver를 제공합니다.


POST /api/plugins/glitter-translate/posts/translations/batch

개념적인 요청은 다음과 같습니다.


{

  "board": "guide",

  "post_ids": [4, 3, 2, 1],

  "fields": ["title"]

}

지원 field는 다음 두 개입니다.


title

content

한 요청에서 처리할 수 있는 Post ID는 최대 100개입니다.

Batch Resolver는 목록의 각 Post마다 Single Resolver를 반복 호출하는

구조를 피하기 위한 API입니다.


Post List

   ↓

현재 page의 Post IDs

   ↓

Batch Resolver 1회

   ↓

Permission-filtered Posts

   ↓

Translations bulk 조회

   ↓

ID별 번역 결과

Post와 Translation을 bulk로 조회하며, per-Post Single Resolver 호출

구조를 사용하지 않습니다.


원본 Fallback

Glitter Translate는 번역 기능이 콘텐츠 표시 자체의 장애 원인이 되지

않도록 원문 fallback을 기본 contract로 사용합니다.


Translation current

→ 번역 표시

Translation missing

→ 원문 표시

Translation stale

→ 원문 표시

Consumer 측에서도 Glitter Translate를 optional integration으로 사용하는

경우에는 Resolver를 사용할 수 없거나 응답이 유효하지 않을 때 원본 Post

값을 유지할 수 있습니다.


Admin Translation Management

관리자에서는 Glitter Translate 전용 번역 관리 화면을 사용할 수 있습니다.

주요 기능은 다음과 같습니다.

  •   Board 선택

  •   Post 검색 및 선택

  •   원문 제목 / 본문 확인

  •   Locale 선택

  •   번역 제목 / 본문 입력

  •   Current / Missing / Stale 상태 확인

  •   번역 저장

  •   번역 삭제

관리자 API와 Public Resolver는 역할을 분리합니다.


Admin API

├─ 번역 목록

├─ Post별 번역 조회

├─ 번역 저장

└─ 번역 삭제

Public API

├─ Single Resolver

└─ Batch Resolver

관리자 번역 변경 기능은 G7 Admin 인증 및 Glitter Translate 권한 경계를

따릅니다.


Translation Storage

번역 데이터는 Glitter Translate 전용 table에서 관리합니다.


g7_glitter_translate_translations

주요 데이터는 다음과 같습니다.


resource_type

resource_id

locale

field

value

content_mode

source_hash

timestamps

다음 조합은 하나의 번역 field를 식별합니다.


resource_type

\+ resource_id

\+ locale

\+ field

즉, 같은 Post에서도 locale과 field별로 번역을 독립적으로 관리할 수

있습니다.

원본 g7_board_posts table에는 번역을 위한 column이나 foreign key를

추가하지 않습니다.


sirsoft-board와의 관계

Glitter Translate 0.2.16의 기능적 dependency는 다음과 같습니다.


sirsoft-board >= 1.1.2

현재 지원하는 번역 resource가 sirsoft-board.post이기 때문입니다.

Plugin이 동작할 때 dependency의 설치 여부, 활성 상태 및 호환 version을

확인합니다.

dependency 조건을 만족하지 못하더라도 기존 번역 데이터를 삭제하지

않습니다.


sirsoft-board

      ↓

Post / Permission

      ↓

Glitter Translate

      ↓

Translation Resolution

Glitter Translate는 sirsoft-board의 Post CRUD나 Resource 구현을

수정하거나 대체하지 않습니다.


Template Integration

Glitter Translate는 특정 User Template에 종속되지 않는 Plugin입니다.

Template은 원본 Post를 기존 G7 방식으로 조회하고, 필요한 presentation

surface에서 Glitter Translate Resolver를 선택적으로 사용할 수 있습니다.


sirsoft-board

      ↓

Permission-filtered Post

      ↓

Glitter Translate Resolver

      ↓

Translated Presentation

현재 integration contract가 적용된 대표적인 Glitter Template은 다음과

같습니다.

Glitter Directory

Glitter Directory 0.5.0에서는 다음 구조를 사용합니다.


Detail

  ↓

Single Resolver

  ↓

title / content translation

Listing

  ↓

Batch Resolver

  ↓

title translation

Glitter Translate는 optional dependency로 취급됩니다.

번역이 없거나 stale 상태이거나 Resolver를 사용할 수 없는 경우에는 원본

Post를 표시합니다.

검색과 category는 기존 sirsoft-board의 원본 semantics를 유지합니다.

Glitter Knowledge

Glitter Knowledge 0.14.0에서는 Home / Collection 문서 목록에서 Batch

Resolver contract를 재사용합니다.


Knowledge Post List

      ↓

Post IDs

      ↓

Batch Resolver

      ↓

Translated title overlay

Glitter Translate 자체를 수정하지 않고 consumer integration으로

연결합니다.

현재 Knowledge는 설치되어 있지만 비활성 상태이므로 active browser

acceptance는 별도의 검증 범위로 남아 있습니다.


검색과 번역의 경계

Glitter Translate 0.2.16은 표시되는 콘텐츠의 번역 resolution을

담당합니다.

검색 index 자체를 다국어화하지 않습니다.

따라서 현재 구조는 다음과 같습니다.


Search

  ↓

sirsoft-board original fields

Presentation

  ↓

Glitter Translate

  ↓

translated title / content

즉, 번역된 제목이나 본문을 검색하는 **Translated Search는 현재 지원하지

않습니다.**


Category 번역의 경계

현재 번역 resource는 sirsoft-board.post이며 지원 field는 title,

content입니다.

따라서 다음 항목은 0.2.0의 번역 대상이 아닙니다.

  •   Board Category

  •   Board metadata 전체

  •   임의의 G7 Resource

  •   다른 Module의 자체 데이터

Glitter Translate 0.2.16은 범용 translation framework가 아니라

**sirsoft-board** Post translation provider로 범위를 명확히

유지합니다.


보안 원칙

Public Resolver와 Admin Translation Management는 서로 다른 권한 경계를

가집니다.

주요 원칙은 다음과 같습니다.

  •   Admin API는 인증 및 plugin permission 확인

  •   Public Resolver는 sirsoft-board Post read permission 재사용

  •   Board / Post 관계 검증

  •   locale allowlist

  •   field allowlist

  •   resource type 고정

  •   Batch Resolver 최대 100 IDs

  •   권한 없는 Post 존재 여부 비노출

  •   Single / Batch permission semantics 일치

  •   원본 콘텐츠 rendering / sanitizer 경계 유지

  •   번역 저장소와 원본 Post 저장소 분리

번역 플러그인이 기존 콘텐츠 보안 경계를 우회하지 않는 것이 기본

원칙입니다.


활용 사례

  •   다국어 커뮤니티 게시글 제공

  •   사용자 가이드의 한국어 / 영어 콘텐츠 운영

  •   Directory 상세 페이지 번역

  •   Directory 목록 제목 번역

  •   Knowledge 문서 목록 번역

  •   Help Center 문서 번역

  •   Editorial 콘텐츠의 다국어 presentation

  •   하나의 원문을 유지하면서 locale별 번역 관리

  •   Template별 번역 DB 구현 없이 공통 Resolver 재사용

  •   목록 화면에서 Batch Resolver를 통한 다국어 title overlay


기술 스택

  •   PHP 8.2+

  •   Laravel 12

  •   GnuBoard7 Plugin Architecture

  •   MariaDB

  •   JSON Layout

  •   Laravel Sanctum

  •   sirsoft-board >= 1.1.2


요구 사항

현재 주요 dependency는 다음과 같습니다.


Plugin ID : glitter-translate

Version : 0.2.16 Vendor    : Glitter.kr

License   : MIT

Required Module

sirsoft-board >= 1.1.2

sirsoft-board는 설치되어 있을 뿐 아니라 활성 상태여야 합니다.


관리자 페이지에서 설치

1. GitHub 저장소에서 설치

GitHub 저장소:


https://github.com/glitter-node/glitter-translate

G7 관리자에서 GitHub 기반 Plugin 설치를 지원하는 환경에서는 위 저장소를

사용하여 설치할 수 있습니다.

설치 후 G7의 정상 Plugin lifecycle을 통해 Glitter Translate를

활성화합니다.

2. Release Package 설치

GitHub Release의 v0.2.16 패키지를 사용할 수 있습니다.


https://github.com/glitter-node/glitter-translate/releases/tag/v0.2.16

배포 패키지는 glitter-translate/를 최상위 디렉터리로 유지합니다.


설치 후 권장 확인

설치 후에는 다음 흐름으로 확인하는 것을 권장합니다.


1\. glitter-translate 설치

        ↓

2\. sirsoft-board dependency 확인

        ↓

3\. glitter-translate 활성화

        ↓

4\. Admin Translation Management 확인

        ↓

5\. Board / Post 선택

        ↓

6\. Locale별 번역 저장

        ↓

7\. Single Resolver 확인

        ↓

8\. 목록 consumer가 있다면 Batch Resolver 확인

        ↓

9\. 원문 변경 후 stale / fallback 확인

        ↓

10\. 권한이 다른 사용자에서 resolver 결과 확인

Public Resolver 사용 구조

Consumer에서는 Glitter Translate의 database를 직접 조회하지 않고

Resolver contract를 사용하는 것을 기본 방향으로 합니다.


Template / Module / Plugin

        ↓

Original Post

        ↓

Glitter Translate Resolver

        ↓

Permission Check

        ↓

Locale Resolution

        ↓

current ?

 ├─ YES → Translation

 └─ NO  → Original

이 구조를 사용하면 번역 저장 방식과 consumer presentation을 분리할 수

있습니다.


API

Public

Single Resolver:


GET /api/plugins/glitter-translate/posts/{slug}/{postId}/translations

Batch Resolver:


POST /api/plugins/glitter-translate/posts/translations/batch

Admin


GET    /api/plugins/glitter-translate/admin/translations

GET    /api/plugins/glitter-translate/admin/posts/{postId}/translations

PUT  
 /api/plugins/glitter-translate/admin/posts/{postId}/translations/{locale}/{field}

DELETE
/api/plugins/glitter-translate/admin/posts/{postId}/translations/{locale}/{field}

Admin endpoint는 번역 관리용이며 Public Resolver와 목적이 다릅니다.


Browser Runtime

v0.2.16부터 Glitter Translate는 번역된 plain-text 본문의 표현 계층을 보완하기 위한 frontend runtime asset을 포함합니다.

브라우저 integration은 번역 본문에 부여된 glitter-translate-content marker 범위에서만 동작하며, standalone HTTP(S) URL line을 progressive link preview로 확장할 수 있습니다.

Translated content
      ↓
content_mode = text
      ↓
glitter-translate-content marker
      ↓
Standalone HTTP(S) URL 감지
      ↓
g7-ckeditor5-superpack link-preview API
      ↓
Glitter Translate preview DOM

이 runtime은 Translation value를 HTML로 다시 저장하거나 변경하지 않습니다. preview를 만들 수 없는 경우에는 기존 plain URL을 그대로 유지합니다.

GlitterTranslate는 제품의 browser namespace로 계속 예약합니다.


현재 지원하지 않는 기능

Glitter Translate 0.2.16에서는 다음 기능을 지원하지 않습니다.

  •   Automatic Translation

  •   AI / 외부 번역 서비스

  •   Translated Search

  •   Category Translation

  •   Translation Memory

  •   Glossary

  •   Collaborative Translation Workflow

  •   범용 G7 Resource Translation

  •   번역된 검색 index

  •   자동 번역 승인 / 검수 workflow

이 항목들은 0.2.16의 미완성 기능이 아니라 후속 버전에서 별도로 검토할 수

있는 확장 범위입니다.


저장소

GitHub


https://github.com/glitter-node/glitter-translate

Release


https://github.com/glitter-node/glitter-translate/releases/tag/v0.2.16

v0.2.14 ~ v0.2.16 콘텐츠 표현 및 링크 프리뷰 업그레이드

v0.2.14 --- Content Representation

번역 본문이 원본 Post의 HTML 표현 방식을 잘못 상속하지 않도록 Translation에 nullable content_mode를 추가했습니다.

  • 새 plain-text 본문 번역은 content_mode=text로 저장합니다.
  • 기존 content translation row의 content_mode는 upgrade migration에서 text로 backfill합니다.
  • current translation은 Translation의 content_mode를 사용합니다.
  • missing/stale translation은 원본 Post의 content와 content_mode를 함께 fallback합니다.
  • Single Resolver와 Batch Resolver가 resolved content representation metadata를 제공합니다.
  • 기존 value, stored_value, source_hash, status contract는 유지합니다.

v0.2.15 --- Replace-mode Renderer Integration

G7의 공식 core.layout_extension.after_apply filter를 사용하여 번역 본문의 representation metadata가 실제 html_content renderer까지 전달되도록 보완했습니다.

특히 replace-mode provider가 host property를 extensionPointProps로 복사하는 경우에도 번역된 content_mode가 최종 renderer에 반영되도록 처리합니다.

이 변경으로 원본 Post가 HTML mode이더라도 번역문이 plain text라면:

Translation.value
      +
Translation.content_mode = text
      ↓
Resolved translated content
      ↓
Text renderer
      ↓
원래 줄바꿈 유지

의 흐름으로 표시됩니다.

원본 HTML 렌더링, sanitizer 경계, Translation value 자체는 변경하지 않습니다.

v0.2.16 --- Progressive Link Preview

번역된 plain-text 본문의 standalone HTTP(S) URL line에 대해 progressive link preview를 지원합니다.

별도의 outbound metadata fetcher를 만들지 않고 g7-ckeditor5-superpack의 공식 link-preview endpoint를 재사용합니다.

주요 동작 원칙:

  • .glitter-translate-content 범위에서만 동작
  • standalone URL line만 preview 대상으로 처리
  • inline URL은 임의로 card로 변환하지 않음
  • 번역문에 실제로 포함된 URL 자체를 preview 대상으로 사용
  • 동일 URL 요청은 browser runtime에서 중복 억제
  • metadata는 textContent 기반으로 안전하게 삽입
  • preview 실패 시 기존 URL을 그대로 유지
  • Translation value와 content_mode=text를 변경하지 않음
  • 원본 rich HTML/CKEditor 콘텐츠의 기존 link-card 동작을 침범하지 않음

따라서 현재 본문 표시 흐름은 다음과 같습니다.

Original Post
   ├─ HTML content → 기존 G7 / editor rendering
   │
   └─ Glitter Translate
        ↓
      Translation.value
        +
      content_mode=text
        ↓
      plain-text renderer
        ↓
      줄바꿈 보존
        ↓
      standalone URL
        ↓
      official link-preview API
        ↓
      progressive preview card

v0.2.13 관리자 번역 관리 안정화

v0.2.13에서는 기존 Single / Batch Resolver의 contract를 유지하면서 실제 관리자 번역 작업 흐름을 안정화했습니다.

Source Post 검색
      ↓
Pagination
      ↓
Post 선택
      ↓
Translation Editor
      ↓
Locale 변경
      ↓
번역 저장 / 삭제

Source Post 응답은 data.data(목록), data.pagination(페이지네이션), data.selection(현재 선택)으로 역할을 구분합니다.

Post를 선택하면 selected Post와 translation DataSource가 자동으로 다시 로드되어 Translation Editor에 현재 대상의 원문과 번역 상태가 표시됩니다. 검색 시에는 선택한 locale을 유지하고, Editor에서 locale을 변경할 때에는 현재 Source Post 페이지와 검색 조건을 유지합니다.

저장된 번역 목록에서는 Post, Locale, Field, Status를 확인하고 개별 translation record를 삭제할 수 있습니다. 원본 Post가 삭제된 뒤 남은 orphan translation도 목록에서 확인하여 명시적으로 정리할 수 있습니다.

API Reference

v0.2.13 배포본에는 현재 구현을 기준으로 작성한 API reference가 포함됩니다.

docs/api/
├── posts.md
├── source-posts.md
└── translations.md

API는 posts, source-posts, translations 세 domain으로 나뉘며 Public Resolver와 Admin Translation Management에서 사용하는 8개 route를 문서화합니다.


버전별 주요 변경

v0.2.16

  • 번역된 plain-text 본문의 standalone HTTP(S) URL에 progressive link preview 추가
  • g7-ckeditor5-superpack 공식 link-preview endpoint 재사용
  • 번역 본문 전용 marker 및 plugin-owned preview presentation 추가
  • Translation value/content mode를 변경하지 않는 progressive enhancement 유지

v0.2.15

  • replace-mode html_content provider의 copied extensionPointProps representation binding 동기화
  • 번역 plain-text 본문이 실제 text renderer에 도달하도록 수정
  • 기존 sanitizer 및 translation value contract 유지

v0.2.14

  • Translation에 nullable content_mode 추가
  • 기존 content translation을 text로 upgrade-safe backfill
  • Single/Batch Resolver에 content representation metadata 추가
  • current translation은 translation mode, missing/stale는 original Post mode 사용
  • 공식 layout extension filter를 통한 renderer integration 추가

v0.2.13

  • Source Post 검색 시 선택한 locale 유지
  • Translation Editor locale 변경 시 Source Post 페이지 및 검색 조건 유지
  • API reference 문서 추가 (posts, source-posts, translations)

v0.2.12

  • Saved Translation Delete action을 neutral secondary button으로 조정
  • Saved Translation 및 Source Post table column 균형과 정렬 개선

v0.2.11

  • post_id 변경 시 selected Post와 translation 자동 reload 복원
  • Translation Editor 표시를 방해하던 manual refetch chain 제거

v0.2.10

  • Source Post selection success 처리의 API response envelope 경로 수정
  • 유효한 Post 선택 시 selected Post와 translation DataSource 갱신 안정화

v0.2.9

  • Source Post 선택 시 실제 Button value를 navigation query에 전달
  • Translation Editor를 열 때 Source Post page와 selector query context 유지

v0.2.8

  • Source Post selection의 API response envelope 참조 수정
  • Post 선택 시 현재 Source Post page 유지

v0.2.7

  • Source Post Selector pagination control 복원
  • pagination.last_page contract 사용

v0.2.6

  • Source Post Selector pagination binding을 실제 pagination response contract에 맞게 수정

v0.2.5

  • 삭제된 Post의 stale selection 정리
  • 저장된 orphan translation을 관리자 정리 대상으로 유지

v0.2.4

  • soft-deleted Source Post를 관리자 selector에서 제외
  • 기존 orphan translation은 Saved Translation List에서 유지

v0.2.3

  • 개별 translation record 삭제 기능 추가
  • Saved Translation List Delete action 및 contextual confirmation 추가
  • 원본 Post를 다시 불러오지 않고 orphan translation 삭제 가능

v0.2.2

  • Plugin backend PHP translation array 복원
  • src/lang → lang 이전 과정에서 유실된 KO/EN messages.php 내용 복구
  • 빈 PHP 언어 파일이 int(1)을 반환하여 Laravel Translation Loader에서 발생하던 HTTP 500 수정
  • Batch Resolver Controller가 사용하는 backend response message key 복원
  • Plugin backend 언어 파일을 공식 lang/{locale}/*.php 구조로 유지
  • API, database schema, resolver contract 변경 없음
  • 기존 Post 및 저장된 번역 데이터 호환성 유지

v0.2.1

  • GitHub/ZIP Plugin 설치 시 backend PHP 언어 파일 경로를 G7 Plugin 공식 구조인 lang/{locale}/*.php로 수정
  • frontend/Layout 번역 파일 resources/lang/{locale}.json 구조 유지

v0.2.0

  • Glitter Translate 첫 공개 기능 세트
  • sirsoft-board Post title / content 수동 번역 관리
  • Admin Translation Management
  • locale별 번역 저장 / 삭제
  • source hash 기반 current / stale 판정
  • missing / stale 원문 fallback
  • Permission-aware Single Resolver
  • Permission-aware Batch Resolver
  • Batch Resolver 최대 100 Post IDs
  • title / content field allowlist
  • Post / Translation bulk resolution
  • Directory Single Resolver consumer compatibility
  • Directory Batch Resolver consumer compatibility
  • Knowledge Batch Resolver contract reuse
  • Admin/Public endpoint 역할 분리
  • KO/EN Admin language resource 제공
  • GlitterTranslate browser namespace 예약

v0.2.2 언어 리소스 안정화 기록

v0.2.2는 기능 범위를 넓히는 릴리스가 아니라 Plugin 패키지와 backend translation runtime을 정상화하는 안정화 릴리스입니다.

G7 Plugin backend 언어 파일은 다음 위치를 사용합니다.

lang/
├── en/
│   └── messages.php
└── ko/
    └── messages.php

각 messages.php는 Laravel이 병합할 수 있는 PHP array를 반환해야 합니다.

<?php

return [
    // translation keys...
];

v0.2.1에서는 경로를 src/lang에서 공식 lang 구조로 바로잡는 과정에서 두 backend 언어 파일의 내용이 비어 있는 상태로 배포될 수 있었고, 빈 PHP 파일을 require한 결과가 int(1)이 되면서 Laravel Translation Loader에서 HTTP 500이 발생했습니다.

v0.2.2에서는 KO/EN translation array와 Batch Resolver 응답에 필요한 message key를 복원했습니다. 이 수정은 번역 데이터 저장 구조, API contract, Single/Batch Resolver의 동작 또는 기존 Post 데이터를 변경하지 않습니다.


개발 상태

v0.2.16 --- Public Release

Glitter Translate는 첫 공개 기능 세트부터 자동 번역 엔진을 만드는 것보다 G7에서

여러 확장이 함께 사용할 수 있는 **번역 데이터와 presentation 사이의

안정적인 경계**를 만드는 데 집중했습니다.

핵심 흐름은 다음과 같습니다.


Original Content

      ↓

Manual Translation

      ↓

Source Hash

      ↓

Locale

      ↓

Post Permission

      ↓

Single / Batch Resolver

      ↓

Translation or Original Fallback

      ↓

Template / Module / Plugin

Glitter Directory에서는 상세 화면의 Single Resolver와 목록 화면의 Batch

Resolver를 통해 실제 consumer integration을 구성했습니다.

Glitter Knowledge에서도 동일한 Batch Resolver contract를 변경 없이

재사용하도록 연결했습니다.

즉, 각 Template이 자체적인 번역 table과 번역 판단 로직을 다시 만드는

대신 Glitter Translate가 번역 provider 역할을 담당하고 consumer는 필요한

presentation surface에서 Resolver를 사용할 수 있습니다.


핵심 구조

glitter-translate의 핵심은 단순히 별도의 언어 문자열을 저장하는 것이

아니라,

**원본 콘텐츠의 소유권은 sirsoft-board에 그대로 두고, 번역 데이터와

번역 상태 판단은 Glitter Translate가 담당하며, 실제 표시 권한은 기존

Post permission을 그대로 따르게 하는 것**

입니다.

즉,


누가 원본을 소유하는가

→ sirsoft-board

누가 번역을 소유하는가

→ Glitter Translate

누가 Post를 볼 수 있는가

→ sirsoft-board Permission

어떤 언어를 사용할 것인가

→ G7 Locale

번역을 지금 사용할 수 있는가

→ Source Hash / Translation Status

번역이 없거나 오래되었는가

→ Original Fallback

여러 Post를 어떻게 효율적으로 처리하는가

→ Batch Resolver

의 책임을 분리합니다.

이를 통해 Template / Module / Plugin이 Glitter Translate의 database

구조를 직접 알지 않고도 동일한 번역 contract를 재사용할 수 있으며,

**원문 → 번역 관리 → 상태 판단 → 권한 확인 → locale resolution →

translated presentation**

의 흐름을 하나의 독립 Plugin으로 연결할 수 있도록 구성했습니다.


현재 릴리스

Release : G7 게시글 번역 관리 플러그인 - Glitter Translate 0.2.16
Tag     : v0.2.16

GitHub 저장소:

https://github.com/glitter-node/glitter-translate

Release:

https://github.com/glitter-node/glitter-translate/releases/tag/v0.2.16

사용 예시: 게시글 목록의 제목을 한 번에 번역하기

게시글 목록처럼 여러 Post의 번역 제목이 필요한 화면에서는 각 게시글마다 Single Resolver를 호출하는 대신 Batch Resolver를 사용할 수 있습니다.

예를 들어 User Template에서 현재 페이지의 게시글을 먼저 조회한 뒤 Post ID를 배열로 만들고 다음 Batch API에 전달합니다.

POST /api/plugins/glitter-translate/posts/translations/batch

요청 예:

{
  "board": "support",
  "post_ids": [65, 51, 50, 27, 23, 7, 3],
  "fields": ["title"]
}

기본적인 처리 흐름은 다음과 같습니다.

게시글 목록 조회
      ↓
현재 페이지의 Post ID 수집
      ↓
Batch Resolver 1회 호출
      ↓
Post별 번역 제목 확인
      ↓
사용할 수 있는 번역이 있으면 번역 제목 표시
      ↓
번역이 없거나 stale 상태이면 원문 제목 표시

이 방식은 게시글마다 번역 API를 각각 호출하지 않으므로 목록 화면에서 per-Post Single Resolver 호출 구조를 피할 수 있습니다.

JSON Layout에서 Post ID 배열 만들기

G7 JSON Layout의 DataSource onSuccess에서 Post ID 배열을 만드는 경우에는 실제 response 구조를 먼저 확인해야 합니다.

예를 들어 사용하는 DataSource에서 실제 Post 배열이 다음 위치에 있다면:

response.data.data.data

현재 페이지의 Post ID 배열은 다음과 같이 만들 수 있습니다.

{{response.data.data.data.map(function(post){return post.id;})}}

평가 결과는 다음과 같은 실제 배열이어야 합니다.

[65, 51, 50, 27, 23, 7, 3]

다만 response.data.data.data는 모든 User Template에서 공통으로 사용하는 고정 경로가 아닙니다.

사용하는 API와 DataSource에 따라 response 구조가 달라질 수 있으므로, 실제 Post 배열이 어느 위치에 있는지 확인한 뒤 해당 경로를 사용해야 합니다.

post_ids는 실제 배열이어야 합니다

Batch Resolver의 post_ids에는 문자열이 아니라 실제 배열이 전달되어야 합니다.

정상적인 값:

[65, 51, 50]

다음과 같이 expression이 평가되지 않은 채 문자열 자체로 전달되는 것은 정상적인 값이 아닙니다.

{{response.data.data.map(post => post.id)}}

또한 다음 값은 배열처럼 보이지만 실제로는 문자열입니다.

"[65,51,50]"

Batch Resolver가 배열을 요구하는 상황에서 post_ids에 이러한 문자열이 전달되면 다음과 같은 422 Unprocessable Content validation 응답이 발생할 수 있습니다.

The post ids field must be an array.

이 오류가 발생한다면 Batch Resolver 자체만 확인하기보다 이전 DataSource에서 Post ID 배열이 정상적으로 생성되었는지 함께 확인하는 것이 좋습니다.

특히 다음 흐름을 순서대로 확인하면 원인을 찾는 데 도움이 됩니다.

원본 DataSource 응답
      ↓
onSuccess response context
      ↓
Post 배열의 실제 위치
      ↓
Post ID 배열 생성
      ↓
Local State
      ↓
Batch Request Payload
      ↓
Translation Result

Chrome DevTools의 Network에서 후속 Batch 요청의 Request Payload를 확인하면 post_ids가 실제 배열인지, 평가되지 않은 expression 문자열인지 구분할 수 있습니다.

핵심

Batch Resolver를 목록 화면에 연결할 때 중요한 것은 특정 expression이나 response 경로를 그대로 복사하는 것이 아니라 다음 두 가지입니다.

  1. 현재 DataSource에서 실제 Post 배열의 위치를 확인할 것
  2. Batch Resolver의 post_ids에 실제 배열 타입을 전달할 것

이 원칙을 지키면 특정 User Template에 종속되지 않고, sirsoft-board의 게시글 목록을 사용하는 다양한 G7 User Template에서 Glitter Translate의 Batch Resolver를 동일한 방식으로 활용할 수 있습니다.

적용 예시

Glitter Translate의 Batch Resolver를 User Template의 게시글 목록에 적용한 실제 예시는 다음 사이트에서 확인할 수 있습니다.

Glitter Project Hub

Glitter Project Hub는 Glitter Translate를 활용하는 하나의 적용 사례이며, Glitter Translate는 특정 User Template에 종속되지 않습니다.


라이선스

MIT License.

Copyright (c) 2026 Glitter.kr

총 2개 댓글
0 / 2,000자
들레아빠
감사 합니다.
Glitter Gim
감사합니다.

다른 창작물 살펴보기