feat: implement backend localization infrastructure
- Add internal/locale package: Parse(Accept-Language), FromContext/WithLang helpers, 12 supported languages - Add Language middleware that reads Accept-Language header and stores lang in context - Register Language middleware globally in server router (after CORS) Database migrations: - 009: create recipe_translations, saved_recipe_translations, ingredient_translations tables; migrate existing _ru data - 010: drop legacy _ru columns (title_ru, description_ru, canonical_name_ru); update FTS index Models: remove all _ru fields (TitleRu, DescriptionRu, NameRu, UnitRu, CanonicalNameRu) Repositories: - recipe: Upsert drops _ru params; GetByID does LEFT JOIN COALESCE on recipe_translations; ListMissingTranslation(lang); UpsertTranslation - ingredient: same pattern with ingredient_translations; Search now queries translated names/aliases - savedrecipe: List/GetByID LEFT JOIN COALESCE on saved_recipe_translations; UpsertTranslation Gemini: - RecipeRequest/MenuRequest gain Lang field - buildRecipePrompt rewritten in English with target-language content instruction; image_query always in English - GenerateMenu propagates Lang to GenerateRecipes Handlers: - recommendation/menu: pass locale.FromContext(ctx) as Lang - recognition: saveClassification stores Russian translation via UpsertTranslation instead of _ru column Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
36
backend/migrations/010_drop_ru_columns.sql
Normal file
36
backend/migrations/010_drop_ru_columns.sql
Normal file
@@ -0,0 +1,36 @@
|
||||
-- +goose Up
|
||||
|
||||
-- Drop the full-text search index that references the soon-to-be-removed
|
||||
-- title_ru column.
|
||||
DROP INDEX IF EXISTS idx_recipes_title_fts;
|
||||
|
||||
-- Remove legacy _ru columns from recipes now that the data lives in
|
||||
-- recipe_translations (migration 009).
|
||||
ALTER TABLE recipes
|
||||
DROP COLUMN IF EXISTS title_ru,
|
||||
DROP COLUMN IF EXISTS description_ru;
|
||||
|
||||
-- Remove the legacy Russian name column from ingredient_mappings.
|
||||
ALTER TABLE ingredient_mappings
|
||||
DROP COLUMN IF EXISTS canonical_name_ru;
|
||||
|
||||
-- Recreate the FTS index on the English title only.
|
||||
-- Cross-language search is now handled at the application level by querying
|
||||
-- the appropriate translation row.
|
||||
CREATE INDEX idx_recipes_title_fts ON recipes
|
||||
USING GIN (to_tsvector('simple', coalesce(title, '')));
|
||||
|
||||
-- +goose Down
|
||||
DROP INDEX IF EXISTS idx_recipes_title_fts;
|
||||
|
||||
ALTER TABLE recipes
|
||||
ADD COLUMN title_ru VARCHAR(500),
|
||||
ADD COLUMN description_ru TEXT;
|
||||
|
||||
ALTER TABLE ingredient_mappings
|
||||
ADD COLUMN canonical_name_ru VARCHAR(255);
|
||||
|
||||
-- Restore the bilingual FTS index.
|
||||
CREATE INDEX idx_recipes_title_fts ON recipes
|
||||
USING GIN (to_tsvector('simple',
|
||||
coalesce(title_ru, '') || ' ' || coalesce(title, '')));
|
||||
Reference in New Issue
Block a user