Initial Global Release v1.0 (Localization & Security Hardening)

This commit is contained in:
leeyj
2026-04-16 01:12:43 +09:00
commit 175a30325b
67 changed files with 6348 additions and 0 deletions
+33
View File
@@ -0,0 +1,33 @@
import re
from ..constants import GROUP_DEFAULT
def parse_metadata(text):
"""
텍스트에서 ##그룹명 과 #태그 추출 유틸리티.
"""
group_name = GROUP_DEFAULT
tags = []
if not text:
return group_name, tags
group_match = re.search(r'##(\S+)', text)
if group_match:
group_name = group_match.group(1)
tag_matches = re.finditer(r'(?<!#)#(\S+)', text)
for match in tag_matches:
tags.append(match.group(1))
return group_name, list(set(tags))
def extract_links(text):
"""
텍스트에서 [[#ID]] 형태의 내부 링크를 찾아 ID 목록(정수)을 반환합니다.
"""
if not text:
return []
# [[#123]] 패턴 매칭
links = re.findall(r'\[\[#(\d+)\]\]', text)
return list(set([int(link_id) for link_id in links]))
+41
View File
@@ -0,0 +1,41 @@
import json
import os
from flask import current_app # type: ignore
class I18n:
_locales = {}
_default_lang = 'en'
@classmethod
def load_locales(cls):
locales_dir = os.path.join(current_app.static_folder, 'locales')
for filename in os.listdir(locales_dir):
if filename.endswith('.json'):
lang = filename.split('.')[0]
with open(os.path.join(locales_dir, filename), 'r', encoding='utf-8') as f:
cls._locales[lang] = json.load(f)
@classmethod
def t(cls, key, lang=None):
if not lang:
# 기본적으로 config에서 언어를 가져오거나 'en' 사용
lang = current_app.config.get('lang', cls._default_lang)
if not cls._locales:
cls.load_locales()
data = cls._locales.get(lang, cls._locales.get(cls._default_lang, {}))
# 중첩 키 지원 (예: "groups.done")
parts = key.split('.')
for p in parts:
if isinstance(data, dict):
data = data.get(p)
else:
return key
return data or key
# 숏컷 함수
def _t(key, lang=None):
return I18n.t(key, lang)