多言語化の基盤作り (#55) (#421)

Reviewed-on: #421
Co-authored-by: miteruzo <miteruzo@naver.com>
このコミットはプルリクエスト #421 でマージされました。
このコミットが含まれているのは:
2026-10-03 02:00:09 +09:00
committed by みてるぞ
コミット e6ab941774
91個のファイルの変更、3370行の追加、1223行の削除
+41 -20
ファイルの表示
@@ -7,6 +7,8 @@ class MaterialsController < ApplicationController
rescue_from MaterialZipExporter::MissingFileError, with: :render_zip_missing_file
def index
locale = resolve_locale!
page = (params[:page].presence || 1).to_i
limit = (params[:limit].presence || 20).to_i
@@ -20,7 +22,7 @@ class MaterialsController < ApplicationController
q = Material.includes(:material_export_items,
thumbnail_attachment: :blob,
file_attachment: :blob,
tag: :tag_name)
tag: :tag_names)
q = q.where(tag_id: nil) if filters[:tag_state] == 'untagged'
q = q.where.not(tag_id: nil) if filters[:tag_state] == 'tagged'
q = apply_material_tag_filter(q, filters, tag_graph)
@@ -42,7 +44,10 @@ class MaterialsController < ApplicationController
.offset(offset)
.to_a
response = { materials: MaterialRepr.list_many(materials, host: request.base_url),
response = { materials: MaterialRepr.list_many(
materials,
host: request.base_url,
language_code: locale.language_code),
count: }
if filters[:tag_id]
response[:tag_scope] = material_index_tag_scope(filters, tag_graph)
@@ -55,6 +60,8 @@ class MaterialsController < ApplicationController
end
def show
locale = resolve_locale!
material =
Material
.includes(:tag, :material_export_items)
@@ -63,15 +70,17 @@ class MaterialsController < ApplicationController
.find_by(id: params[:id])
return head :not_found unless material
wiki_page_body = material.tag&.tag_name&.wiki_page&.current_revision&.body
wiki_page_body = material.tag&.tag_name('ja')&.wiki_page&.current_revision&.body
render json: MaterialRepr.base(material, host: request.base_url).merge(wiki_page_body:)
render json: MaterialRepr.base(material, host: request.base_url,
language_code: locale.language_code).merge(wiki_page_body:)
end
def create
return head :unauthorized unless current_user
return head :forbidden unless current_user.gte_member?
locale = resolve_locale!
tag_name_raw = params[:tag].to_s.strip
file = params[:file]
file_sha256 = MaterialFileSha256.from_upload(file)
@@ -89,13 +98,14 @@ class MaterialsController < ApplicationController
begin
Material.transaction do
tag = resolve_material_tag!(tag_name_raw)
tag = resolve_material_tag!(locale, tag_name_raw)
material = Material.new(tag:, url:,
created_by_user: current_user,
updated_by_user: current_user)
material.file.attach(uploaded_blob) if uploaded_blob
material.save!
TagVersioning.record_tag_snapshot!(tag, created_by_user: current_user)
TagVersioning.record_tag_snapshot!(tag, created_by_user: current_user,
language_code: locale.language_code)
upsert_export_paths!(material)
MaterialVersionRecorder.record!(material:, event_type: :create,
created_by_user: current_user)
@@ -107,7 +117,8 @@ class MaterialsController < ApplicationController
if material
log_thumbnail_generation(material, MaterialThumbnailGenerator.generate!(material))
render json: MaterialRepr.base(material, host: request.base_url), status: :created
render json: MaterialRepr.base(material, host: request.base_url,
language_code: locale.language_code), status: :created
else
render_validation_error material
end
@@ -132,12 +143,14 @@ class MaterialsController < ApplicationController
block = MaterialImportBlockMatcher.match_for_sha256(file_sha256)
return render_material_import_block(block) if block
locale = resolve_locale!
uploaded_blob = build_uploaded_material_blob!(file, file_sha256)
begin
Material.transaction do
MaterialVersionRecorder.ensure_snapshot!(material, created_by_user: current_user)
tag = resolve_material_tag!(tag_name_raw)
tag = resolve_material_tag!(locale, tag_name_raw)
material.assign_attributes(tag:, url:, updated_by_user: current_user)
if uploaded_blob
material.file.attach(uploaded_blob)
@@ -145,7 +158,8 @@ class MaterialsController < ApplicationController
material.file.detach
end
material.save!
TagVersioning.record_tag_snapshot!(tag, created_by_user: current_user)
TagVersioning.record_tag_snapshot!(tag, created_by_user: current_user,
language_code: locale.language_code)
upsert_export_paths!(material)
MaterialVersionRecorder.record!(material:, event_type: :update,
created_by_user: current_user)
@@ -157,7 +171,8 @@ class MaterialsController < ApplicationController
log_thumbnail_generation(material, MaterialThumbnailGenerator.generate!(material))
render json: MaterialRepr.base(material, host: request.base_url)
render json: MaterialRepr.base(material, host: request.base_url,
language_code: locale.language_code)
end
def destroy
@@ -236,10 +251,8 @@ class MaterialsController < ApplicationController
nil
end
def resolve_material_tag! tag_name_raw
tag_name = TagName.find_or_create_by!(name: tag_name_raw)
tag = tag_name.tag
tag || Tag.create!(tag_name:, category: :material)
def resolve_material_tag! locale, tag_name_raw
Tag.find_or_create_by_tag_name!(locale, tag_name_raw, category: :material)
end
def material_index_needs_tag_name? filters
@@ -253,7 +266,12 @@ class MaterialsController < ApplicationController
end
def material_index_join_tag_name q
q.left_joins(tag: :tag_name)
q.left_joins(:tag).joins(<<~SQL.squish)
LEFT JOIN tag_names
ON tag_names.tag_id = tags.id
AND tag_names.language_code = 'ja'
AND tag_names.primary_flg = TRUE
SQL
end
def material_index_join_file_blob q
@@ -269,9 +287,11 @@ class MaterialsController < ApplicationController
def apply_material_query q, term
like = "%#{ ActiveRecord::Base.sanitize_sql_like(term) }%"
q.where('tag_names.name LIKE :q OR materials.url LIKE :q OR ' \
'material_file_blobs.filename LIKE :q',
q: like)
q.where(<<~SQL.squish, q: like)
tag_names.name LIKE :q
OR materials.url LIKE :q
OR material_file_blobs.filename LIKE :q
SQL
end
def apply_material_media_kind q, media_kind
@@ -323,8 +343,9 @@ class MaterialsController < ApplicationController
end
tags_by_id =
Tag
.joins(:tag_name)
.where(id: scope_tag_ids)
.joins(:tag_names)
.where(id: scope_tag_ids,
tag_names: { language_code: 'ja', primary_flg: true })
.pluck('tags.id', 'tag_names.name', 'tags.category', 'tags.deprecated_at')
.each_with_object({ }) do |(id, name, category, deprecated_at), hash|
hash[id] = { id:, name:, category:, deprecated: deprecated_at.present? }