dolibarr 25.0.0-alpha
traduction.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2005-2018 Regis Houssin <regis.houssin@inodbox.com>
3 * Copyright (C) 2007 Rodolphe Quiedeville <rodolphe@quiedeville.org>
4 * Copyright (C) 2010-2012 Destailleur Laurent <eldy@users.sourceforge.net>
5 * Copyright (C) 2014 Henry Florian <florian.henry@open-concept.pro>
6 * Copyright (C) 2023 Benjamin Falière <benjamin.faliere@altairis.fr>
7 * Copyright (C) 2024-2026 Frédéric France <frederic.france@free.fr>
8 * Copyright (C) 2026 MDW <mdeweerd@users.noreply.github.com>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 3 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program. If not, see <https://www.gnu.org/licenses/>.
22 * or see https://www.gnu.org/
23 */
24
31// Load Dolibarr environment
32require '../main.inc.php';
41require_once DOL_DOCUMENT_ROOT.'/core/lib/product.lib.php';
42require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
43require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
44require_once DOL_DOCUMENT_ROOT.'/core/class/html.formadmin.class.php';
45require_once DOL_DOCUMENT_ROOT.'/product/class/productlang.class.php';
46
55// Load translation files required by the page
56$langs->loadLangs(array('products', 'languages'));
57
58$id = GETPOSTINT('id');
59$ref = GETPOST('ref', 'alpha');
60$action = GETPOST('action', 'aZ09');
61$cancel = GETPOST('cancel', 'alpha');
62
63// Security check
64$fieldvalue = (!empty($id) ? $id : (!empty($ref) ? $ref : ''));
65$fieldtype = (!empty($ref) ? 'ref' : 'rowid');
66if ($user->socid) {
67 $socid = $user->socid;
68}
69
70$object = new Product($db);
71if ($id > 0 || !empty($ref)) {
72 $object->fetch($id, $ref);
73}
74
75// Extrafields of the translations (element product_lang)
76$extrafields->fetch_name_optionals_label('product_lang');
77$productlanghasextrafields = !empty($extrafields->attributes['product_lang']['count']);
78if ($object->id > 0 && $productlanghasextrafields) {
79 $object->getMultiLangs(1);
80}
81
82// Initialize a technical object to manage hooks of page. Note that conf->hooks_modules contains an array of hook context
83$hookmanager->initHooks(array('producttranslationcard', 'globalcard'));
84
85if ($object->id > 0) {
86 if ($object->type == $object::TYPE_PRODUCT) {
87 restrictedArea($user, 'produit', $object->id, 'product&product', '', '');
88 }
89 if ($object->type == $object::TYPE_SERVICE) {
90 restrictedArea($user, 'service', $object->id, 'product&product', '', '');
91 }
92} else {
93 restrictedArea($user, 'produit|service', $fieldvalue, 'product&product', '', '', $fieldtype);
94}
95
96// Permissions
97$usercancreate = (($object->type == Product::TYPE_PRODUCT && $user->hasRight('produit', 'creer')) || ($object->type == Product::TYPE_SERVICE && $user->hasRight('service', 'creer')));
98
99
100/*
101 * Actions
102 */
103
104$parameters = array('id'=>$id, 'ref'=>$ref);
105$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
106if ($reshook < 0) {
107 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
108}
109if (empty($reshook)) {
110 // return to translation display if cancelled
111 if ($cancel == $langs->trans("Cancel")) {
112 $action = '';
113 }
114
115 if ($action == 'delete' && GETPOST('langtodelete', 'alpha') && $usercancreate) {
116 $object->delMultiLangs(GETPOST('langtodelete', 'alpha'), $user);
117 setEventMessages($langs->trans("RecordDeleted"), null, 'mesgs');
118 header('Location:'.$_SERVER['PHP_SELF'].'?id='.$id);
119 exit;
120 }
121
122 // Add translation
123 if ($action == 'vadd' && $cancel != $langs->trans("Cancel") && $usercancreate) {
124 $current_lang = $langs->getDefaultLang();
125
126 // update de l'objet
127 if (GETPOST("forcelangprod") == $current_lang) {
128 $object->label = GETPOST("libelle");
129 $object->description = dol_htmlcleanlastbr(GETPOST("desc", 'restricthtml'));
130 $object->other = dol_htmlcleanlastbr(GETPOST("other", 'restricthtml'));
131
132 $result = $object->update($object->id, $user, 1); // trigger will be called by setMultiLangs
133 if ($result < 0) {
134 setEventMessages($object->error, $object->errors, 'errors');
135 }
136 } else {
137 $object->multilangs[GETPOST("forcelangprod")]["label"] = GETPOST("libelle");
138 $object->multilangs[GETPOST("forcelangprod")]["description"] = dol_htmlcleanlastbr(GETPOST("desc", 'restricthtml'));
139 $object->multilangs[GETPOST("forcelangprod")]["other"] = dol_htmlcleanlastbr(GETPOST("other", 'restricthtml'));
140 }
141
142 if ($productlanghasextrafields && GETPOST("forcelangprod")) {
143 $object->multilangs[GETPOST("forcelangprod")]["array_options"] = $extrafields->getOptionalsFromPost('product_lang');
144 }
145
146 // save in database
147 if (GETPOST("forcelangprod")) {
148 $result = $object->setMultiLangs($user);
149 } else {
150 $object->error = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Language"));
151 $result = -1;
152 }
153
154 if ($result > 0) {
155 header('Location:'.$_SERVER['PHP_SELF'].'?id='.$id);
156 exit;
157 } else {
158 $action = 'add';
159 setEventMessages($object->error, $object->errors, 'errors');
160 }
161 }
162
163 // Edit translation
164 if ($action == 'vedit' && $cancel != $langs->trans("Cancel") && $usercancreate) {
165 $current_lang = $langs->getDefaultLang();
166
167 foreach ($object->multilangs as $key => $value) { // Record the new values in the object
168 if ($key == $current_lang) {
169 $object->label = GETPOST("libelle-" . $key);
170 $object->description = dol_htmlcleanlastbr(GETPOST("desc-" . $key, 'restricthtml'));
171 $object->other = dol_htmlcleanlastbr(GETPOST("other-" . $key, 'restricthtml'));
172
173 $result = $object->update($object->id, $user);
174 if ($result < 0) {
175 setEventMessages($object->error, $object->errors, 'errors');
176 }
177 } else {
178 $object->multilangs[$key]["label"] = GETPOST("libelle-" . $key);
179 $object->multilangs[$key]["description"] = dol_htmlcleanlastbr(GETPOST("desc-" . $key, 'restricthtml'));
180 $object->multilangs[$key]["other"] = dol_htmlcleanlastbr(GETPOST("other-" . $key, 'restricthtml'));
181 }
182 if ($productlanghasextrafields) {
183 $object->multilangs[$key]["array_options"] = $extrafields->getOptionalsFromPost('product_lang', '-'.$key);
184 }
185 }
186
187 $result = $object->setMultiLangs($user);
188 if ($result > 0) {
189 header('Location:'.$_SERVER['PHP_SELF'].'?id='.$id);
190 exit;
191 } else {
192 $action = 'edit';
193 setEventMessages($object->error, $object->errors, 'errors');
194 }
195 }
196
197 // Delete translation
198 if ($action == 'vdelete' && $cancel != $langs->trans("Cancel") && $usercancreate) {
199 $langtodelete = GETPOST('langdel', 'alpha');
200
201 $result = $object->delMultiLangs($langtodelete, $user);
202 if ($result > 0) {
203 header('Location:'.$_SERVER['PHP_SELF'].'?id='.$id);
204 exit;
205 } else {
206 $action = 'edit';
207 setEventMessages($object->error, $object->errors, 'errors');
208 }
209 }
210}
211
212
213/*
214 * View
215 */
216
217$title = $langs->trans('ProductServiceCard');
218$helpurl = '';
219$shortlabel = dol_trunc($object->label, 16);
220if (GETPOST("type") == '0' || ($object->type == Product::TYPE_PRODUCT)) {
221 $title = $langs->trans('Product')." ".$shortlabel." - ".$langs->trans('Translation');
222 $helpurl = 'EN:Module_Products|FR:Module_Produits|ES:M&oacute;dulo_Productos';
223}
224if (GETPOST("type") == '1' || ($object->type == Product::TYPE_SERVICE)) {
225 $title = $langs->trans('Service')." ".$shortlabel." - ".$langs->trans('Translation');
226 $helpurl = 'EN:Module_Services_En|FR:Module_Services|ES:M&oacute;dulo_Servicios';
227}
228
229llxHeader('', $title, $helpurl, '', 0, 0, '', '', '', 'mod-product page-translation');
230
231$form = new Form($db);
232$formadmin = new FormAdmin($db);
233
234$head = product_prepare_head($object);
235$titre = $langs->trans("CardProduct".$object->type);
236$picto = ($object->type == Product::TYPE_SERVICE ? 'service' : 'product');
237
238
239// Calculate $cnt_trans
240$cnt_trans = 0;
241if (!empty($object->multilangs)) {
242 foreach ($object->multilangs as $key => $value) {
243 $cnt_trans++;
244 }
245}
246
247
248print dol_get_fiche_head($head, 'translation', $titre, 0, $picto);
249
250$linkback = '<a href="'.DOL_URL_ROOT.'/product/list.php?restore_lastsearch_values=1&type='.$object->type.'">'.$langs->trans("BackToList").'</a>';
251
252$shownav = 1;
253if ($user->socid && !in_array('product', explode(',', getDolGlobalString('MAIN_MODULES_FOR_EXTERNAL')))) {
254 $shownav = 0;
255}
256
257dol_banner_tab($object, 'ref', $linkback, $shownav, 'ref', '', '', '', 0, '', '', 1);
258
259print dol_get_fiche_end();
260
261
262
263/*
264 * Action bar
265 */
266print "\n".'<div class="tabsAction">'."\n";
267
268$parameters = array();
269$reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been
270if (empty($reshook)) {
271 if ($action == '') {
272 if ($user->hasRight('produit', 'creer') || $user->hasRight('service', 'creer')) {
273 print '<a class="butAction" href="' . DOL_URL_ROOT . '/product/traduction.php?action=add&token='.newToken().'&id=' . $object->id . '">' . $langs->trans("Add") . '</a>';
274 if ($cnt_trans > 0) {
275 print '<a class="butAction" href="' . DOL_URL_ROOT . '/product/traduction.php?action=edit&token='.newToken().'&id=' . $object->id . '">' . $langs->trans("Modify") . '</a>';
276 }
277 }
278 }
279}
280
281print "\n".'</div>'."\n";
282
283
284
285if ($action == 'edit') {
286 //WYSIWYG Editor
287 require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
288
289 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
290 print '<input type="hidden" name="token" value="'.newToken().'">';
291 print '<input type="hidden" name="action" value="vedit">';
292 print '<input type="hidden" name="id" value="'.$object->id.'">';
293
294 if (!empty($object->multilangs)) {
295 $i = 0;
296 foreach ($object->multilangs as $key => $value) {
297 $i++;
298
299 $s = picto_from_langcode((string) $key);
300 print($i > 1 ? "<br>" : "").($s ? $s.' ' : '').' <div class="inline-block margintop marginbottomonly"><b>'.$langs->trans('Language_'.$key).'</b></div><div class="inline-block floatright"><a href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=delete&token='.newToken().'&langtodelete='.$key.'">'.img_delete('', 'class="valigntextbottom marginrightonly"').'</a></div>';
301
302 print '<div class="underbanner clearboth"></div>';
303 print '<table class="border centpercent">';
304 print '<tr><td class="titlefieldcreate fieldrequired">'.$langs->trans('Label').'</td><td><input name="libelle-'.$key.'" size="40" value="'.dol_escape_htmltag($object->multilangs[$key]["label"]).'"></td></tr>';
305 print '<tr><td class="tdtop">'.$langs->trans('Description').'</td><td>';
306 $doleditor = new DolEditor("desc-$key", $object->multilangs[$key]["description"], '', 160, 'dolibarr_notes', '', false, true, getDolGlobalInt('FCKEDITOR_ENABLE_DETAILS'), ROWS_3, '90%');
307 $doleditor->Create();
308 print '</td></tr>';
309 if (getDolGlobalString('PRODUCT_USE_OTHER_FIELD_IN_TRANSLATION')) {
310 print '<tr><td class="tdtop">'.$langs->trans("NotePrivate").'</td><td>';
311 $doleditor = new DolEditor("other-$key", $object->multilangs[$key]["other"], '', 160, 'dolibarr_notes', '', false, true, getDolGlobalInt('FCKEDITOR_ENABLE_DETAILS'), ROWS_3, '90%');
312 $doleditor->Create();
313 }
314 print '</td></tr>';
315 // Extrafields of the translation
316 if ($productlanghasextrafields) {
317 $productlang = new ProductLang($db);
318 $productlang->id = $object->multilangs[$key]["rowid"];
319 $productlang->array_options = (empty($object->multilangs[$key]["array_options"]) ? array() : $object->multilangs[$key]["array_options"]);
320 print $productlang->showOptionals($extrafields, 'edit', array(), '-'.$key);
321 }
322 print '</table>';
323 }
324 }
325
326 $parameters = array();
327 $reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
328
329 print '<br>';
330
331 print $form->buttonsSaveCancel();
332
333 print '</form>';
334} elseif ($action != 'add') {
335 if (!empty($object->multilangs)) {
336 $i = 0;
337 foreach ($object->multilangs as $key => $value) {
338 $i++;
339
340 $s = picto_from_langcode((string) $key);
341 print($i > 1 ? "<br>" : "").($s ? $s.' ' : '').' <div class="inline-block marginbottomonly"><b>'.$langs->trans('Language_'.$key).'</b></div><div class="inline-block floatright"><a href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=delete&token='.newToken().'&langtodelete='.$key.'">'.img_delete('', 'class="valigntextbottom marginrightonly"').'</a></div>';
342
343 print '<div class="fichecenter">';
344 print '<div class="underbanner clearboth"></div>';
345 print '<table class="border centpercent">';
346 print '<tr><td class="titlefieldcreate">'.$langs->trans('Label').'</td><td>'.$object->multilangs[$key]["label"].'</td></tr>';
347 print '<tr><td class="tdtop">'.$langs->trans('Description').'</td><td>'.$object->multilangs[$key]["description"].'</td></tr>';
348 if (getDolGlobalString('PRODUCT_USE_OTHER_FIELD_IN_TRANSLATION')) {
349 print '<tr><td>'.$langs->trans("NotePrivate").'</td><td>'.$object->multilangs[$key]["other"].'</td></tr>';
350 }
351 // Extrafields of the translation
352 if ($productlanghasextrafields) {
353 $productlang = new ProductLang($db);
354 $productlang->id = $object->multilangs[$key]["rowid"];
355 $productlang->array_options = (empty($object->multilangs[$key]["array_options"]) ? array() : $object->multilangs[$key]["array_options"]);
356 print $productlang->showOptionals($extrafields, 'view');
357 }
358 print '</table>';
359 print '</div>';
360 }
361 }
362 if (!$cnt_trans && $action != 'add') {
363 print '<div class="opacitymedium">'.$langs->trans('NoTranslation').'</div>';
364 }
365}
366
367
368
369/*
370 * Form to add a new translation
371 */
372
373if ($action == 'add' && ($user->hasRight('produit', 'creer') || $user->hasRight('service', 'creer'))) {
374 //WYSIWYG Editor
375 require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
376
377 print '<br>';
378 print '<form action="'.$_SERVER["PHP_SELF"].'" method="post">';
379 print '<input type="hidden" name="token" value="'.newToken().'">';
380 print '<input type="hidden" name="action" value="vadd">';
381 print '<input type="hidden" name="id" value="'.GETPOSTINT("id").'">';
382
383 print dol_get_fiche_head();
384
385 print '<table class="border centpercent">';
386 print '<tr><td class="tdtop titlefieldcreate fieldrequired">'.$langs->trans('Language').'</td><td>';
387 print $formadmin->select_language(GETPOST('forcelangprod'), 'forcelangprod', 0, $object->multilangs, 1);
388 print '</td></tr>';
389 print '<tr><td class="tdtop fieldrequired">'.$langs->trans('Label').'</td><td><input name="libelle" size="40"></td></tr>';
390 print '<tr><td class="tdtop">'.$langs->trans('Description').'</td><td>';
391 $doleditor = new DolEditor('desc', '', '', 160, 'dolibarr_notes', '', false, true, getDolGlobalInt('FCKEDITOR_ENABLE_DETAILS'), ROWS_3, '90%');
392 $doleditor->Create();
393 print '</td></tr>';
394 // Other field (not used)
395 if (getDolGlobalString('PRODUCT_USE_OTHER_FIELD_IN_TRANSLATION')) {
396 print '<tr><td class="tdtop">'.$langs->trans('NotePrivate').'</td><td>';
397 $doleditor = new DolEditor('other', '', '', 160, 'dolibarr_notes', '', false, true, getDolGlobalInt('FCKEDITOR_ENABLE_DETAILS'), ROWS_3, '90%');
398 $doleditor->Create();
399 print '</td></tr>';
400 }
401 // Extrafields of the translation
402 if ($productlanghasextrafields) {
403 $productlang = new ProductLang($db);
404 print $productlang->showOptionals($extrafields, 'create');
405 }
406 print '</table>';
407
408 $parameters = array();
409 $reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
410
411 print dol_get_fiche_end();
412
413 print $form->buttonsSaveCancel();
414
415 print '</form>';
416
417 print '<br>';
418}
419
420// End of page
421llxFooter();
422$db->close();
$id
Support class for third parties, contacts, members, users or resources.
Definition account.php:47
if(! $sortfield) if(! $sortorder) $object
Definition account.php:100
llxFooter($comment='', $zone='private', $disabledoutputofmessages=0)
Empty footer.
Definition wrapper.php:91
if(!defined('NOREQUIRESOC')) if(!defined( 'NOREQUIRETRAN')) if(!defined('NOTOKENRENEWAL')) if(!defined( 'NOREQUIREMENU')) if(!defined('NOREQUIREHTML')) if(!defined( 'NOREQUIREAJAX')) llxHeader($head='', $title='', $help_url='', $target='', $disablejs=0, $disablehead=0, $arrayofjs='', $arrayofcss='', $morequerystring='', $morecssonbody='', $replacemainareaby='', $disablenofollow=0, $disablenoindex=0)
Empty header.
Definition wrapper.php:73
Class to manage a WYSIWYG editor.
Class to generate html code for admin pages.
Class to manage generation of HTML components Only common components must be here.
Class to manage products or services.
const TYPE_PRODUCT
Regular product.
const TYPE_SERVICE
Service.
Class of a translation of a product (a row of llx_product_lang).
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
newToken()
Return the value of token currently saved into session with name 'newtoken'.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0, $nodefault=0)
Return value of a param into GET or POST supervariable.
dol_htmlcleanlastbr($stringtodecode)
This function remove all ending and br at end.
GETPOSTINT($paramname, $method=0, $nodefault=0)
Return the value of a $_GET or $_POST supervariable, converted into integer.
dol_trunc($string, $size=40, $trunc='right', $stringencoding='UTF-8', $nodot=0, $display=0)
Truncate a string to a particular length adding '...' if string larger than length.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
picto_from_langcode($codelang, $moreatt='', $notitlealt=0)
Return img flag of country for a language code or country code.
dol_get_fiche_head($links=array(), $active='', $title='', $notab=0, $picto='', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limittoshow=0, $moretabssuffix='', $dragdropfile=0, $morecssdiv='')
Show tabs of a record.
Definition html.lib.php:540
dol_get_fiche_end($notab=0)
Return tab footer of a card.
Definition html.lib.php:738
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0, $cleanalsojavascript=0)
Definition html.lib.php:181
product_prepare_head($object)
Prepare array with list of tabs.
restrictedArea(User $user, $features, $object=0, $tableandshare='', $feature2='', $dbt_keyfield='fk_soc', $dbt_select='rowid', $isdraft=0, $nodie=0, $mode='')
Check permissions of a user to show a page and an object.