Skip to content

Commit 8b37373

Browse files
authored
Merge pull request #371 from ma10/freee_a11y_gl-config-handling-improvement-20250708
tools/lib/freee_a11y_glの設定ファイルの扱いを見直し
2 parents 752802e + 5ff604c commit 8b37373

File tree

19 files changed

+1792
-990
lines changed

19 files changed

+1792
-990
lines changed

package-lock.json

Lines changed: 1076 additions & 660 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@
2121
"ajv": "^8.17.1",
2222
"ajv-cli": "^5.0.0",
2323
"husky": "^9.1.7",
24-
"lint-staged": "^15.5.1",
24+
"lint-staged": "^16.1.2",
2525
"sudachi-synonyms-dictionary": "^14.0.0",
26-
"textlint": "^14.6.0",
26+
"textlint": "^15.2.0",
2727
"textlint-filter-rule-allowlist": "^4.0.0",
2828
"textlint-plugin-rst": "^0.1.1",
2929
"textlint-rule-ja-hiragana-fukushi": "^1.3.0",
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
graft src/freee_a11y_gl/data

tools/lib/freee_a11y_gl/pyproject.toml

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
44

55
[project]
66
name = "freee_a11y_gl"
7-
version = "0.1.4"
7+
version = "0.2.0"
88
description = "A module to process a11y guidelines data"
99
authors = [
1010
{name = "Masafumi NAKANE", email = "[email protected]"}
@@ -13,8 +13,13 @@ requires-python = ">=3.8"
1313
dependencies = [
1414
"pyyaml>=6.0",
1515
"gitpython>=3.1.43",
16-
"pydantic>=2.7.0"
16+
"pydantic>=2.7.0",
17+
"importlib_resources>=1.3.0; python_version<'3.9'"
1718
]
1819

1920
[tool.setuptools]
2021
package-dir = { "" = "src" }
22+
include-package-data = true
23+
24+
[tool.setuptools.package-data]
25+
freee_a11y_gl = ["data/*.yaml"]

tools/lib/freee_a11y_gl/src/freee_a11y_gl/config.py

Lines changed: 105 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
"""Configuration interface for freee_a11y_gl module."""
2-
import re
3-
from typing import Dict, Literal, Optional
2+
from typing import Any, Dict, List, Literal, Optional
43
from .settings import settings
54

65
LanguageCode = Literal["ja", "en"]
@@ -9,8 +8,81 @@ class Config:
98
"""Configuration interface."""
109

1110
@classmethod
12-
def register_settings(cls, new_settings: Optional[Dict[str, any]] = None) -> None:
13-
"""Register new settings."""
11+
def initialize(cls, profile: Optional[str] = None, config_override: Optional[Dict[str, Any]] = None) -> None:
12+
"""Initialize configuration with profile and overrides.
13+
14+
This method allows you to initialize the library's configuration with a specific
15+
profile and optional configuration overrides. This is the recommended way to
16+
configure the library for different use cases.
17+
18+
Args:
19+
profile: Profile name to use (e.g., "yaml2rst", "yaml2sheet", "custom_project").
20+
If None, uses "default" profile.
21+
config_override: Dictionary of settings to override. Can contain nested
22+
dictionaries for hierarchical configuration.
23+
24+
Examples:
25+
# Use a specific profile
26+
Config.initialize(profile="yaml2rst")
27+
28+
# Use profile with custom overrides
29+
Config.initialize(
30+
profile="yaml2sheet",
31+
config_override={
32+
"base_url": "https://custom.example.com",
33+
"basedir": "/path/to/project",
34+
"languages": {
35+
"default": "en"
36+
},
37+
"paths": {
38+
"guidelines": "/custom/categories/"
39+
}
40+
}
41+
)
42+
43+
Note:
44+
This method should be called before using other Config methods.
45+
Settings are validated after initialization. Localized strings should
46+
be configured through message catalog files, not through config_override.
47+
"""
48+
settings.initialize(profile=profile, config_override=config_override)
49+
50+
@classmethod
51+
def register_settings(cls, new_settings: Optional[Dict[str, Any]] = None) -> None:
52+
"""Register new settings with validation.
53+
54+
This method allows you to customize the library's configuration by providing
55+
a dictionary of settings that will be merged with the existing configuration.
56+
57+
Args:
58+
new_settings: Dictionary of settings to register. Can contain nested
59+
dictionaries for hierarchical configuration.
60+
61+
Examples:
62+
# Simple configuration
63+
Config.register_settings({
64+
"base_url": "https://custom.example.com"
65+
})
66+
67+
# Complex nested configuration
68+
Config.register_settings({
69+
"base_url": "https://custom.example.com",
70+
"basedir": "/path/to/project",
71+
"languages": {
72+
"default": "en",
73+
"available": ["ja", "en"]
74+
},
75+
"paths": {
76+
"guidelines": "/custom/categories/",
77+
"faq": "/custom/faq/"
78+
}
79+
})
80+
81+
Note:
82+
Settings are validated after registration. Invalid configurations
83+
will raise a validation error. Localized strings should be configured
84+
through message catalog files, not through this method.
85+
"""
1486
settings.update(new_settings)
1587

1688
@classmethod
@@ -68,19 +140,19 @@ def get_separator(cls, lang: Optional[LanguageCode] = None, separator_type: Opti
68140
"""Get separator of specified type for language."""
69141
effective_lang = lang if lang is not None else settings.get("languages.default", "ja")
70142
effective_type = separator_type if separator_type is not None else "text"
71-
return settings.get(f"locale.{effective_lang}.{effective_type}_separator", "")
143+
return settings.message_catalog.get_separator(effective_type, effective_lang)
72144

73145
@classmethod
74146
def get_text_separator(cls, lang: Optional[LanguageCode] = None) -> str:
75147
"""Get text separator for specified language."""
76148
effective_lang = lang if lang is not None else settings.get("languages.default", "ja")
77-
return settings.get(f"locale.{effective_lang}.text_separator", "")
149+
return settings.message_catalog.get_separator("text", effective_lang)
78150

79151
@classmethod
80152
def get_list_separator(cls, lang: Optional[LanguageCode] = None) -> str:
81153
"""Get list item separator for specified language."""
82154
effective_lang = lang if lang is not None else settings.get("languages.default", "ja")
83-
return settings.get(f"locale.{effective_lang}.list_separator", ", ")
155+
return settings.message_catalog.get_separator("list", effective_lang)
84156

85157
@classmethod
86158
def get_pass_singular_text(cls, lang: Optional[LanguageCode] = None) -> str:
@@ -93,7 +165,7 @@ def get_pass_singular_text(cls, lang: Optional[LanguageCode] = None) -> str:
93165
Localized pass text for single condition
94166
"""
95167
effective_lang = lang if lang is not None else settings.get("languages.default", "ja")
96-
return settings.get(f"locale.{effective_lang}.pass_singular_text", " is true")
168+
return settings.message_catalog.get_pass_text("singular", effective_lang)
97169

98170
@classmethod
99171
def get_pass_plural_text(cls, lang: Optional[LanguageCode] = None) -> str:
@@ -106,68 +178,38 @@ def get_pass_plural_text(cls, lang: Optional[LanguageCode] = None) -> str:
106178
Localized pass text for multiple conditions
107179
"""
108180
effective_lang = lang if lang is not None else settings.get("languages.default", "ja")
109-
return settings.get(f"locale.{effective_lang}.pass_plural_text", " are true")
181+
return settings.message_catalog.get_pass_text("plural", effective_lang)
110182

111183
@classmethod
112184
def get_conjunction(cls, lang: Optional[LanguageCode] = None, conjunction_type: Optional[str] = None) -> str:
113185
"""Get conjunction of specified type for language."""
114186
effective_lang = lang if lang is not None else settings.get("languages.default", "ja")
115187
effective_type = conjunction_type if conjunction_type is not None else "and"
116-
return settings.get(f"locale.{effective_lang}.{effective_type}_conjunction", "and")
188+
return settings.message_catalog.get_conjunction(effective_type, effective_lang)
117189

118190
@classmethod
119191
def get_check_tool_name(cls, tool_id: str, lang: Optional[LanguageCode] = None) -> str:
120192
"""Get localized check tool name."""
121193
effective_lang = lang if lang is not None else settings.get("languages.default", "ja")
122-
try:
123-
return settings.config.check_tools.names[tool_id][effective_lang]
124-
except (KeyError, AttributeError):
125-
return tool_id
194+
return settings.message_catalog.get_check_tool(tool_id, effective_lang)
126195

127196
@classmethod
128197
def get_check_target_name(cls, target: str, lang: Optional[LanguageCode] = None) -> str:
129198
"""Get localized check target name."""
130199
effective_lang = lang if lang is not None else settings.get("languages.default", "ja")
131-
try:
132-
return settings.config.check_targets.names[target][effective_lang]
133-
except (KeyError, AttributeError):
134-
return target
200+
return settings.message_catalog.get_check_target(target, effective_lang)
135201

136202
@classmethod
137203
def get_severity_tag(cls, severity: str, lang: Optional[LanguageCode] = None) -> str:
138204
"""Get localized severity tag."""
139205
effective_lang = lang if lang is not None else settings.get("languages.default", "ja")
140-
try:
141-
return settings.config.severity_tags.tags[severity][effective_lang]
142-
except (KeyError, AttributeError):
143-
return severity
144-
145-
@classmethod
146-
def get_implementation_target_name(cls, target: str, lang: Optional[LanguageCode] = None) -> str:
147-
"""Get localized implementation target name."""
148-
effective_lang = lang if lang is not None else settings.get("languages.default", "ja")
149-
try:
150-
return settings.config.implementation_targets.targets[target][effective_lang]
151-
except (KeyError, AttributeError):
152-
return target
206+
return settings.message_catalog.get_severity_tag(severity, effective_lang)
153207

154208
@classmethod
155209
def get_platform_name(cls, platform: str, lang: Optional[LanguageCode] = None) -> str:
156210
"""Get localized platform name."""
157211
effective_lang = lang if lang is not None else settings.get("languages.default", "ja")
158-
try:
159-
return settings.config.platform.names[effective_lang][platform]
160-
except (KeyError, AttributeError):
161-
return platform
162-
163-
@classmethod
164-
def get_platform_separator(cls, lang: Optional[LanguageCode] = None) -> str:
165-
"""Get platform list separator for specified language."""
166-
effective_lang = lang if lang is not None else settings.get("languages.default", "ja")
167-
try:
168-
return settings.config.platform.separator[effective_lang]
169-
except (KeyError, AttributeError):
170-
return ", "
212+
return settings.message_catalog.get_platform_name(platform, effective_lang)
171213

172214
@classmethod
173215
def get_faq_path(cls) -> str:
@@ -201,5 +243,22 @@ def get_date_format(cls, lang: Optional[LanguageCode] = None) -> str:
201243
Date format string in strftime format
202244
"""
203245
effective_lang = lang if lang is not None else settings.get("languages.default", "ja")
204-
default_format = "%Y年%-m月%-d日" if effective_lang == "ja" else "%B %-d, %Y"
205-
return settings.get(f"locale.{effective_lang}.date_format", default_format)
246+
return settings.message_catalog.get_date_format("default", effective_lang)
247+
248+
@classmethod
249+
def get_available_languages(cls) -> List[str]:
250+
"""Get list of available languages.
251+
252+
Returns:
253+
List of available language codes
254+
"""
255+
return settings.get("languages.available", ["ja", "en"])
256+
257+
@classmethod
258+
def get_default_language(cls) -> str:
259+
"""Get default language code.
260+
261+
Returns:
262+
Default language code
263+
"""
264+
return settings.get("languages.default", "ja")

tools/lib/freee_a11y_gl/src/freee_a11y_gl/config.yaml.sample

Lines changed: 0 additions & 82 deletions
This file was deleted.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
"""Data package for freee_a11y_gl."""
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Default configuration for freee_a11y_gl
2+
# This file contains default values for all configuration settings
3+
# All default values are externalized from Python code for consistency
4+
5+
languages:
6+
available: ["ja", "en"]
7+
default: "ja"
8+
9+
base_url: "https://a11y-guidelines.freee.co.jp"
10+
11+
paths:
12+
guidelines: "/categories/"
13+
faq: "/faq/articles/"
14+
15+
# Profile-specific configurations
16+
profiles:
17+
yaml2rst:
18+
# yaml2rst script specific settings
19+
# Inherits all default settings above
20+
description: "Configuration profile for yaml2rst script"
21+
22+
yaml2sheet:
23+
# yaml2sheet script specific settings
24+
# Inherits all default settings above
25+
description: "Configuration profile for yaml2sheet script"

0 commit comments

Comments
 (0)