diff --git a/deploy/translate_campsite_type.sql b/deploy/translate_campsite_type.sql new file mode 100644 index 0000000..d982d16 --- /dev/null +++ b/deploy/translate_campsite_type.sql @@ -0,0 +1,26 @@ +-- Deploy camper:translate_campsite_type to pg +-- requires: roles +-- requires: schema_camper +-- requires: campsite_type_i18n + +begin; + +set search_path to camper, public; + +create or replace function translate_campsite_type (slug uuid, lang_tag text, name text, description text) returns void as +$$ + insert into campsite_type_i18n (campsite_type_id, lang_tag, name, description) + select campsite_type_id, translate_campsite_type.lang_tag, translate_campsite_type.name, xmlparse(content coalesce(translate_campsite_type.description, '')) + from campsite_type + where slug = translate_campsite_type.slug + on conflict (campsite_type_id, lang_tag) do update + set name = excluded.name + , description = excluded.description +$$ + language sql +; + +revoke execute on function translate_campsite_type (uuid, text, text, text) from public; +grant execute on function translate_campsite_type(uuid, text, text, text) to admin; + +commit; diff --git a/pkg/campsite/types/l10n.go b/pkg/campsite/types/l10n.go index 1528da8..13fd4df 100644 --- a/pkg/campsite/types/l10n.go +++ b/pkg/campsite/types/l10n.go @@ -64,15 +64,7 @@ func editTypeL10n(w http.ResponseWriter, r *http.Request, user *auth.User, compa l10n.MustRender(w, r, user, company) return } - conn.MustExec(r.Context(), ` - insert into campsite_type_i18n (campsite_type_id, lang_tag, name, description) - select campsite_type_id, $1, $2, $3 - from campsite_type - where slug = $4 - on conflict (campsite_type_id, lang_tag) do update - set name = excluded.name - , description = excluded.description - `, l10n.Locale.Language, l10n.Name, l10n.Description, l10n.Slug) + conn.MustExec(r.Context(), "select translate_campsite_type($1, $2, $3, $4)", l10n.Slug, l10n.Locale.Language, l10n.Name, l10n.Description) httplib.Redirect(w, r, "/admin/campsites/types", http.StatusSeeOther) } diff --git a/po/ca.po b/po/ca.po index b72d552..5f9fd94 100644 --- a/po/ca.po +++ b/po/ca.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: camper\n" "Report-Msgid-Bugs-To: jordi@tandem.blog\n" -"POT-Creation-Date: 2023-09-15 00:05+0200\n" +"POT-Creation-Date: 2023-09-15 01:21+0200\n" "PO-Revision-Date: 2023-07-22 23:45+0200\n" "Last-Translator: jordi fita mas \n" "Language-Team: Catalan \n" @@ -525,8 +525,8 @@ msgctxt "language option" msgid "Automatic" msgstr "Automàtic" -#: pkg/app/user.go:249 pkg/campsite/types/l10n.go:90 -#: pkg/campsite/types/admin.go:293 pkg/season/admin.go:203 +#: pkg/app/user.go:249 pkg/campsite/types/l10n.go:82 +#: pkg/campsite/types/admin.go:294 pkg/season/admin.go:203 msgid "Name can not be empty." msgstr "No podeu deixar el nom en blanc." @@ -538,7 +538,7 @@ msgstr "La confirmació no es correspon amb la contrasenya." msgid "Selected language is not valid." msgstr "L’idioma escollit no és vàlid." -#: pkg/app/user.go:253 pkg/campsite/types/admin.go:295 pkg/home/carousel.go:286 +#: pkg/app/user.go:253 pkg/campsite/types/admin.go:296 pkg/home/carousel.go:287 msgid "File must be a valid PNG or JPEG image." msgstr "El fitxer has de ser una imatge PNG o JPEG vàlida." @@ -546,7 +546,7 @@ msgstr "El fitxer has de ser una imatge PNG o JPEG vàlida." msgid "Access forbidden" msgstr "Accés prohibit" -#: pkg/campsite/types/admin.go:297 +#: pkg/campsite/types/admin.go:298 msgid "Cover image can not be empty." msgstr "No podeu deixar la imatge de portada en blanc." @@ -630,7 +630,7 @@ msgstr "No podeu deixar el format del número de factura en blanc." msgid "Cross-site request forgery detected." msgstr "S’ha detectat un intent de falsificació de petició a llocs creuats." -#: pkg/home/carousel.go:288 +#: pkg/home/carousel.go:289 msgid "Slide image can not be empty." msgstr "No podeu deixar la imatge de la diapositiva en blanc." diff --git a/po/es.po b/po/es.po index 0bf06d6..6f2cf55 100644 --- a/po/es.po +++ b/po/es.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: camper\n" "Report-Msgid-Bugs-To: jordi@tandem.blog\n" -"POT-Creation-Date: 2023-09-15 00:05+0200\n" +"POT-Creation-Date: 2023-09-15 01:21+0200\n" "PO-Revision-Date: 2023-07-22 23:46+0200\n" "Last-Translator: jordi fita mas \n" "Language-Team: Spanish \n" @@ -525,8 +525,8 @@ msgctxt "language option" msgid "Automatic" msgstr "Automático" -#: pkg/app/user.go:249 pkg/campsite/types/l10n.go:90 -#: pkg/campsite/types/admin.go:293 pkg/season/admin.go:203 +#: pkg/app/user.go:249 pkg/campsite/types/l10n.go:82 +#: pkg/campsite/types/admin.go:294 pkg/season/admin.go:203 msgid "Name can not be empty." msgstr "No podéis dejar el nombre en blanco." @@ -538,7 +538,7 @@ msgstr "La confirmación no se corresponde con la contraseña." msgid "Selected language is not valid." msgstr "El idioma escogido no es válido." -#: pkg/app/user.go:253 pkg/campsite/types/admin.go:295 pkg/home/carousel.go:286 +#: pkg/app/user.go:253 pkg/campsite/types/admin.go:296 pkg/home/carousel.go:287 msgid "File must be a valid PNG or JPEG image." msgstr "El archivo tiene que ser una imagen PNG o JPEG válida." @@ -546,7 +546,7 @@ msgstr "El archivo tiene que ser una imagen PNG o JPEG válida." msgid "Access forbidden" msgstr "Acceso prohibido" -#: pkg/campsite/types/admin.go:297 +#: pkg/campsite/types/admin.go:298 msgid "Cover image can not be empty." msgstr "No podéis dejar la imagen de portada en blanco." @@ -630,7 +630,7 @@ msgstr "No podéis dejar el formato de número de factura en blanco." msgid "Cross-site request forgery detected." msgstr "Se ha detectado un intento de falsificación de petición en sitios cruzados." -#: pkg/home/carousel.go:288 +#: pkg/home/carousel.go:289 msgid "Slide image can not be empty." msgstr "No podéis dejar la imagen de la diapositiva en blanco." diff --git a/revert/translate_campsite_type.sql b/revert/translate_campsite_type.sql new file mode 100644 index 0000000..256c123 --- /dev/null +++ b/revert/translate_campsite_type.sql @@ -0,0 +1,7 @@ +-- Revert camper:translate_campsite_type from pg + +begin; + +drop function if exists camper.translate_campsite_type(uuid, text, text, text); + +commit; diff --git a/sqitch.plan b/sqitch.plan index 7894401..cbd5391 100644 --- a/sqitch.plan +++ b/sqitch.plan @@ -45,6 +45,7 @@ add_media [roles schema_camper media media_type] 2023-09-08T17:40:28Z jordi fita media_path [roles schema_camper media] 2023-09-13T22:50:14Z jordi fita mas # Add function to get the URL path of a media campsite_type [roles schema_camper company media user_profile] 2023-07-31T11:20:29Z jordi fita mas # Add relation of campsite type campsite_type_i18n [roles schema_camper campsite_type language] 2023-09-12T10:31:29Z jordi fita mas # Add relation for campsite_type translations +translate_campsite_type [roles schema_camper campsite_type_i18n] 2023-09-14T23:08:50Z jordi fita mas # Add function to translate a campsite type add_campsite_type [roles schema_camper campsite_type company] 2023-08-04T16:14:48Z jordi fita mas # Add function to create campsite types edit_campsite_type [roles schema_camper campsite_type company] 2023-08-07T22:21:34Z jordi fita mas # Add function to edit campsite types campsite [roles schema_camper company campsite_type user_profile] 2023-08-14T10:11:51Z jordi fita mas # Add campsite relation diff --git a/test/translate_campsite_type.sql b/test/translate_campsite_type.sql new file mode 100644 index 0000000..84657e4 --- /dev/null +++ b/test/translate_campsite_type.sql @@ -0,0 +1,77 @@ +-- Test translate_campsite_type +set client_min_messages to warning; +create extension if not exists pgtap; +reset client_min_messages; + +begin; + +select plan(13); + +set search_path to camper, public; + +select has_function('camper', 'translate_campsite_type', array['uuid', 'text', 'text', 'text']); +select function_lang_is('camper', 'translate_campsite_type', array['uuid', 'text', 'text', 'text'], 'sql'); +select function_returns('camper', 'translate_campsite_type', array['uuid', 'text', 'text', 'text'], 'void'); +select isnt_definer('camper', 'translate_campsite_type', array['uuid', 'text', 'text', 'text']); +select volatility_is('camper', 'translate_campsite_type', array['uuid', 'text', 'text', 'text'], 'volatile'); +select function_privs_are('camper', 'translate_campsite_type', array['uuid', 'text', 'text', 'text'], 'guest', array[]::text[]); +select function_privs_are('camper', 'translate_campsite_type', array['uuid', 'text', 'text', 'text'], 'employee', array[]::text[]); +select function_privs_are('camper', 'translate_campsite_type', array['uuid', 'text', 'text', 'text'], 'admin', array['EXECUTE']); +select function_privs_are('camper', 'translate_campsite_type', array['uuid', 'text', 'text', 'text'], 'authenticator', array[]::text[]); + + +set client_min_messages to warning; +truncate campsite_type cascade; +truncate media cascade; +truncate company cascade; +reset client_min_messages; + +insert into company (company_id, business_name, vatin, trade_name, phone, email, web, address, city, province, postal_code, country_code, currency_code, default_lang_tag) +values (1, 'Company 2', 'XX123', '', '555-555-555', 'a@a', '', '', '', '', '', 'ES', 'EUR', 'ca') +; + +insert into media (media_id, company_id, original_filename, media_type, content) +values (2, 1, 'cover2.xpm', 'image/x-xpixmap', 'static char *s[]={"1 1 1 1","a c #ffffff","a"};') + , (3, 1, 'cover3.xpm', 'image/x-xpixmap', 'static char *s[]={"1 1 1 1","a c #ff00ff","a"};') + , (4, 1, 'cover4.xpm', 'image/x-xpixmap', 'static char *s[]={"1 1 1 1","a c #ffff00","a"};') +; + +insert into campsite_type (company_id, slug, media_id, name, description, active) +values (1, '87452b88-b48f-48d3-bb6c-0296de64164e', 2, 'Type A', '

A

', true) + , (1, '9b6370f7-f941-46f2-bc6e-de455675bd0a', 3, 'Type B', '

B

', false) +; + +insert into campsite_type_i18n (campsite_type_id, lang_tag, name, description) +select campsite_type_id, 'ca', 'tipusb', '

B

' from campsite_type +where slug = '9b6370f7-f941-46f2-bc6e-de455675bd0a' +; + +select lives_ok( + $$ select translate_campsite_type('87452b88-b48f-48d3-bb6c-0296de64164e', 'ca', 'Tipus A', '

a

') $$, + 'Should be able to translate the first type' +); + +select lives_ok( + $$ select translate_campsite_type('9b6370f7-f941-46f2-bc6e-de455675bd0a', 'es', 'Tipo B', '

b

') $$, + 'Should be able to translate the second type' +); + +select lives_ok( + $$ select translate_campsite_type('9b6370f7-f941-46f2-bc6e-de455675bd0a', 'ca', 'Tipus B', null) $$, + 'Should be able to overwrite the catalan translation of the second type, with no description' +); + +select bag_eq( + $$ select slug::text, lang_tag, i18n.name, i18n.description::text from campsite_type_i18n as i18n join campsite_type using (campsite_type_id) $$, + $$ values ('87452b88-b48f-48d3-bb6c-0296de64164e', 'ca', 'Tipus A', '

a

') + , ('9b6370f7-f941-46f2-bc6e-de455675bd0a', 'ca', 'Tipus B', '') + , ('9b6370f7-f941-46f2-bc6e-de455675bd0a', 'es', 'Tipo B', '

b

') + $$, + 'Should have added and updated all translations.' +); + + +select * +from finish(); + +rollback; diff --git a/verify/translate_campsite_type.sql b/verify/translate_campsite_type.sql new file mode 100644 index 0000000..f5c79d9 --- /dev/null +++ b/verify/translate_campsite_type.sql @@ -0,0 +1,7 @@ +-- Verify camper:translate_campsite_type on pg + +begin; + +select has_function_privilege('camper.translate_campsite_type(uuid, text, text, text)', 'execute'); + +rollback;