i18N Wordpress using mo files not accepting context - wordpress

I am getting a bit confused with loading my themes .MO file.
I have did a lot of searching on google and I got a version working but I don't understand why.
First of all, I have set my text domain in the themes CSS file:
Text Domain: beauty
I started out with the Roots theme, which does the after_setup_theme and I load the MO file there:
load_theme_textdomain('beauty', get_template_directory() . '/lang');
This MO file has a 'beauty' context and a 'roots' context.
The MO file is loading, cause when I dump $l10n[$domain] I see my 3 values the have the beauty context.
For the sake of space I will show only one entry:
array (size=3)
'beautyInloggen' =>
object(Translation_Entry)[218]
public 'is_plural' => boolean false
public 'context' => string 'beauty' (length=6)
public 'singular' => string 'Inloggen' (length=8)
public 'plural' => null
public 'translations' =>
array (size=1)
0 => string 'Login' (length=5)
public 'translator_comments' => string '' (length=0)
public 'extracted_comments' => string '' (length=0)
public 'references' =>
array (size=0)
empty
public 'flags' =>
array (size=0)
empty
I have 2 locals in my site, nl_NL and en_UK. This are set using WPML and are loaded correctly.
I have a nl_NL.mo and an en_UK.mo file in the lang folder of the theme.
So, this all looks good.
However, in my header.php I have a login anchor:
<?php _e( 'Inloggen', 'beauty' ); ?>
which in my understanding should load the context 'beauty' and the key 'Inloggen'.
So, it doesn't work when I am in my locale nl_UK, I see the standard Dutch text of 'Inloggen' instead of 'Login'.
Strangely, when I remove the msgctxt "beauty" context from my PO file and save it to create a new MO file, it DOES work.
I have used contexts before in my plugin where I use load_textdomain for loading MO files and that works fine.
The reason I want to use contexts is because the one file contains Roots and Beauty related texts and I am only interested in the Beauty texts. I don't want to remove all the _e entries of the Roots theme so it doesn't come up when I load sources.
So that was one question.
Question 2 is less important but also puzzling me: When I look at the example of the theme twentyfiftheen the have their PO and MO files in the wp-content/languages/themes/ folder as twentyfiftheen-nl_NL.mo.
I read this great article (https://localise.biz/help/wordpress/loading-translations) and this post (https://wordpress.stackexchange.com/questions/137427/themes-text-domain-language-po-file-not-working) and understood that you should always give the MO file the name of the locale and not of the contextname + locale.
In this nice doc (https://localise.biz/help/wordpress/loading-translations) I find
So in short, WordPress will look in only two places for a theme's MO file:
{absolute_path}/{locale}.mo
wp-content/languages/themes/{domain}-{locale}.mo
e.g. for twentyfourteen's French translations:
wp-content/themes/twentyfourteen/languages/fr_FR.mo
wp-content/languages/themes/twentyfourteen-fr_FR.mo
However, when I had my MO/PO file in the wp-content/languages/themes it wasn't working, but It could be related to the same issue I have with the context (question 1).
cheers

Okay, I found out that I abused the Context attribute in POEdit as if it was a domain.
I was confused by another post thinking that it would work like that.
Well it doesn't.
So I did what #Václav Slavík recommended and wrapped the _e and __ functions into my own functions so that POEdit could search for those end I would not get the Roots language tags in my files.
Problem solved.
It also loads from the default language folder of Wordpress, it was all related to the context/domain confusion.

Related

error when rendering Symfony 4 edit form that includes a File type

I'm following the steps outlined in this documentation https://symfony.com/doc/current/controller/upload_file.html to allow a file to be uploaded. It is working perfectly for adding a new item, but when I try to edit my entity, I'm getting the following error:
The form's view data is expected to be an instance of class Symfony\Component\HttpFoundation\File\File, but is a(n) string. You can avoid this error by setting the "data_class" option to null or by adding a view transformer that transforms a(n) string to an instance of Symfony\Component\HttpFoundation\File\File.
I've tried code like what is suggested in that article to append the path of the folder as File type to the entity like this in my update method:
public function editAction(Request $request, Advertiser $advertiser)
{
$advertiser->setLogo(
new File($this->getParameter('logo_directory') .'/' . $advertiser->getLogo())
);
$editForm = $this->createForm(AdvertiserType::class, $advertiser);
$editForm->handleRequest($request);
if ($editForm->isSubmitted() && $editForm->isValid()) {
$this->getDoctrine()->getManager()->flush();
return $this->redirectToRoute('advertiser_list');
}
return $this->render('advertiser/index.html.twig', [
'form' => $editForm->createView()
]);
}
The logo_directory parameter is properly defined (and working fine for creating new entities).
Please let me know if you have any ideas what I am doing wrong.
Thanks for the help.
UPDATE: In this article The form's view data is expected to be an instance of class ... but is a(n) string there is a proposed solution to include in the form builder code the following:
->add('file', FileType::class, array('data_class' => null))
So I'm doing this now and the edit form will show - but it doesn't prepoulate with the previous selection.
->add('logo', FileType::class, array('data_class' => null), ['label' => 'Logo (JPG or PNG file)'])
Any thoughts on how this can be changed to allow the form to show with the previous selection pre-populated?
Setting a null data_class will remove the warning but it will not work, you don't need it at this point.
This is due to the fact that once your file is persisted, what remains in your database is just a path, not the file itself (which is on disk);
If you want to edit this entity again, the path (a string) must be converted to a File entity again; That's what the error message says.
.. and this is what you did when you wrote :
$advertiser->setLogo(
new File($this->getParameter('logo_directory') .'/' . $advertiser->getLogo())
);
Now, the problem that remains is that you want to prepopulate the file field. In fact, that is not possible, since the file field points to a location in your own computer, not to a file on your server (and you cannot automatically upload something from someone's computer like that, that would be very dangerous).
What you want to do is possibly indicate that a file is already stored, get its path and maybe display it to your user.
So in your Twig template, something like that (change with your real logo directory) :
{% if form.logo.vars.data %}
<img src="{{ asset('/uploads/logos_directory/' ~ form.logo.vars.data.filename) }}"/>
{% endif %}
Hope it's clear.

SilverStripe edit gridfield success message on save

What's the easiest way to edit the default success message when saving an item in GridField edit view?
The message seems to be in a variable in class GridFieldDetailForm within method doSave.
$message = _t(
'GridFieldDetailForm.Saved',
'Saved {name} {link}',
array(
'name' => $this->record->i18n_singular_name(),
'link' => $link
)
);
Since the message uses the _t() function it will attempt to fetch the value defined in the lang file corresponding to the current user's locale. The default string defined in the function is just a fallback for when no translation could be found within the lang files.
To change the message you can update your site's yml lang file located in mysite/lang/{LANGUAGE_CODE}.yml
For english this would be:
# mysite/lang/en.yml
# remember to flush after editing me :-)
en:
GridFieldDetailForm:
Saved: 'My custom message using {name} and here is a link to the object: {link}'
https://docs.silverstripe.org/en/3.4/developer_guides/i18n/
Something like this should work for specific implementations
$form = $gridField->getConfig()->getComponentByType('GridFieldDetailForm');
$form->setItemEditFormCallback(function($form, $itemRequest)
{
// Replace save action with custom method in here
});
For more general implementations, you'll likely want to extend GridFieldDetailForm and override doSave, then replace the GridFieldDetailForm component with your custom class.

Module multi image upload

I'm using the following module for uploading multiple images:
https://github.com/bummzack/sortablefile
I use the has-many relationship.
class PortfolioPage extends Page
{
private static $has_many = array(
'Images' => 'PortfolioImage'
);
class PortfolioImage extends Image
{
private static $has_one = array(
'PortfolioPage' => 'PortfolioPage'
);
}
The problem is that when uploading multiple images with the same file name it gives me the following error: File with the same name already exists .
How can I avoid this such that it will be possible to upload multiple images when they have the same filename?
Thank you
SortableUploadField is extending the UploadField, try adding setOverwriteWarning to False in your getCMSFields section. Check the code below:
$uploadField = new SortableUploadField('Images', 'Upload Images');
$uploadField->setOverwriteWarning(FALSE);
$fields->addFieldToTab("Root.Main", $uploadField);
Take note, this only prevents the error and rename the duplicate file name. Example: if you upload same file name like file.jpg, the second file.jpg will be renamed to 2.jpg, 3.jpg, etc.
Actually this error is "natural" behavior, it's impossible to store multiple files with identical names in one directory.
Please read discussion on GitHub for more information.

Get localized string for specific locale

How can I use the localization mechanism in WordPress to get access to an existing but not-current language string?
Background: I have a custom theme where I use locale 'en_US' as the default locale and translate through a PO file to locale 'es_ES' (Spanish).
Let us say I use the construction
__('Introduction', 'my_domain');
in my code, and that I have translated 'Introduction' to the Spanish 'Introducción´ in my PO file. All this works fine.
Now to the problem: I want to insert n records in my database with all existing translations of the string 'Introduction' - one for each language; so, n = 2 in my example.
Ideally, I would write something like this:
$site_id = 123;
// Get an array of all defined locales: ['en_US', 'es_ES']
$locales = util::get_all_locales();
// Add one new record in table details for each locale with the translated target string
foreach ($locales as $locale) {
db::insert_details($site_id, 'intro',
__('Introduction', 'my_domain', $locale), $locale);
}
Only, that the 3rd parameter in __() above is pure fantasy on my part. You can only validly write
__('Introduction', 'my_domain');
to get either 'Introduction' or 'Introducción' depending on the current locale.
The outcome of the code above would ideally be that I end up with two records in my table:
SITE_ID CAT TEXT LOCALE
123 intro Introduction en_US
123 intro Introducción es_ES
I am aware that I want something that requires loading all the MO files, where normally, only the MO file for the current language is required. Maybe use of the WordPress function load_textdomain is necessary - I was just hoping there already exists a solution.
Expanding on the question by including the plugin PolyLang: is it possible to use Custom Strings to achieve the above functionality? E.g. conceptually:
pll_('Introduction', $locale)
Old question I know, but here goes -
Starting with a simple example where you know exactly what locales to load and exactly where the MO files are, you could use the MO loader directly:
<?php
$locales = array( 'en_US', 'es_ES' );
foreach( $locales as $tmp_locale ){
$mo = new MO;
$mofile = get_template_directory().'/languages/'.$tmp_locale.'.mo';
$mo->import_from_file( $mofile );
// get what you need directly
$translation = $mo->translate('Introduction');
}
This assumes your MO files are all under the theme. If you wanted to put more of this logic through the WordPress's environment you could, but it's a bit nasty. Example:
<?php
global $locale;
// pull list of installed language codes
$locales = get_available_languages();
$locales[] = 'en_US';
// we need to know the Text Domain and path of what we're translating
$domain = 'my_domain';
$mopath = get_template_directory() . '/languages';
// iterate over locales, finally restoring the original en_US
foreach( $locales as $switch_locale ){
// hack the global locale variable (better to use a filter though)
$locale = $switch_locale;
// critical to unload domain before loading another
unload_textdomain( $domain );
// call the domain loader - here using the specific theme utility
load_theme_textdomain( $domain, $mopath );
// Use translation functions as normal
$translation = __('Introduction', $domain );
}
This method is nastier because it hacks globals and requires restoring your original locale afterwards, but it has the advantage of using WordPress's internal logic for loading your theme's translations. That would be useful if they were in different locations, or if their locations were subject to filters.
I also used get_available_languages in this example, but note that you'll need the core language packs to be installed for this. It won't pick up Spanish in your theme unless you've also installed the core Spanish files.

directory separator in cakephp disables my CSS

is what I get, everytime I use this,
$certpath = APP."Plugin".DS."PaypalIpn".DS."Controller".DS."Certificates".DS;
in my code, it ruins my css. Well, not necessarily ruins but my page is as if not using any css for its alignment or other stuff.
i need that DS since i have to call a file in that directory
$encryption['cert_file'] = $certpath.$encryption['cert_file'];
I tried this:
$encryption['key_file'] = $certpath.DS.$encryption['key_file'];
$encryption['cert_file'] = $certpath.DS.$encryption['cert_file'];
$encryption['paypal_cert_file'] = $certpath.DS.$encryption['paypal_cert_file'];
Still no luck. The first two lines work that way, but the third one doesn't.
And I tried googling with these keywords:
directory separator in cakephp ruins my css
uses of directory separator in cakephp
calling files using directory separator in cakephp
but none of it helped me.
DS is just a directory separator right? What could possibly be wrong?
.......... edited part
well this is another issue, I found the culprit from my previous issue but please do explain so how it is related to my problem. this is my PaypalHelper.php
<?php
$importConfig = array(
'type' => 'File',
'name' => 'PaypalIpn.ppcrypto',
//'file' => CONFIGS .'paypal_ipn_config.php'
'file' => APP."Plugin".DS."paypal_ipn".DS."libs".DS."ppcrypto.php"
);
//... other codes
//..other functions
function button($title, $options = array(), $buttonOptions = array()) {
//..other codes
$certpath = APP."Plugin".DS."PaypalIpn".DS."Controller".DS."Certificates".DS;
//..other codes
}
?>
see this code?
$importConfig = array(
'type' => 'File',
'name' => 'PaypalIpn.ppcrypto',
//'file' => CONFIGS .'paypal_ipn_config.php'
'file' => APP."Plugin".DS."paypal_ipn".DS."libs".DS."ppcrypto.php"
);
and this?
$certpath = APP."Plugin".DS."PaypalIpn".DS."Controller".DS."Certificates".DS;
$encryption['paypal_cert_file'] = $certpath.$encryption['paypal_cert_file'];
the $importConfig..it was wrong coz it should be
$importConfig = array(
'type' => 'File',
'name' => 'PaypalIpn.ppcrypto',
//'file' => CONFIGS .'paypal_ipn_config.php'
'file' => APP."Plugin".DS."PaypalIpn".DS."libs".DS."ppcrypto.php"
);
..but when i tried to correct it, $encryption['paypal_cert_file'] worked fine. It doesn't ruins/(disables??) my css
i put this as an answer first but i believe there are still questions raising in my head..
I am almost certain whatever is or was wrong is either a fatal error or some kind of other error output messing up your HTML output.
Sometimes even with debugging enabled the error isn't visible on the screen and you must check the HTML source, especially if the error occurs in the <head> section of the HTML, inside Javascript or before the closing > of a tag. I would suggest that when you fixed the error, it fixed your problem.
I would double check that you have debugging enabled. See CakePHP Core Configuration from the cake documentation.
If you have fixed the problem but still want to know what caused it, if possible, undo your changes and check what I have mentioned above. Other than that I don't see anything immediately obvious in your code which could have cause the problem.

Resources