I have completed my plugin, now want to provide a multilingual features for my users. I goggled about it, but it's hard to implement.
I've seen WordPress translation but need basic steps to follow and translate my plugin.
I have done these
downloaded POEdit.
created 'french.po' file in plugin dir
complied 'french.po' -> 'french.mo'
Need to do
How to define msgid & msgstr in po file?
How to load po/mo file in plugin?
How to replace labels/text through po/mo file?
how to use __e() & ___() to replace 'msgstr' in plugin pages?
With a plugin called, Codestyling Localization, you don't need to use POEdit.
I'll show you an example of using 'localizationsample' as the text domain. In this case, the language files are in the /lang/ directory. They don't need to be those names in your actual plugin; they are just examples.
Steps
Add these lines in the plugin comment header to be recognized by Codestyling Localization.
Text Domain: localizationsample
Domain Path: /lang
Create a directory named lang in your plugin directory.
Install and activate the Codestyling Localization plugin.
Go to Tools -> Localization
Find your plugin and click on Add New Language
Select the language (country) to localize in the radio button and press Create po-file At this point make sure a .po file is created in the lang folder.
Press Rescan -> scan now This is recommended since in my system without doing this, the plugin always shows an error saying "not all items are using the same text domain."
Press Edit This will bring you another page listing the messages available to be translated. Those messages are the ones passed to the functions __() and _e() in the plugin code.
Click on Edit in the table next to Copy then you'll get a dialog box to type your translation for each message. Finish translating.
Press generate mo-file At this point, you should see a .mo file being created in the lang folder.
Change your locale specified in wp-config.php to reflect the translation. The default is define('WPLANG', '');
Sample plugin
/*
Plugin Name: Sample Localization
Description: Demonstrates how to localize your plugin.
Text Domain: localizationsample
Domain Path: /lang
*/
// Localization
add_action('init', 'localizationsample_init');
function localizationsample_init() {
$path = dirname(plugin_basename( __FILE__ )) . '/lang/';
$loaded = load_plugin_textdomain( 'localizationsample', false, $path);
if ($_GET['page'] == basename(__FILE__) && !$loaded) {
echo '<div class="error">Sample Localization: ' . __('Could not load the localization file: ' . $path, 'localizationsample') . '</div>';
return;
}
}
// Add Admin Menu
add_action('admin_menu','localizationsample_menu');
function localizationsample_menu() {
add_options_page(
'Localization Demo', // admin page title
'Localization Demo', // menu item name
'manage_options', // access privilege
basename(__FILE__), // page slug for the option page
'localization_demo_adminpanel' // call-back function name
);
}
function localization_demo_adminpanel() {
echo '<div class="wrap"><div id="icon-themes" class="icon32"></div>';
echo '<h2>' . __('Hi there!', 'localizationsample') . '</h2>';
echo '<p>';
_e('Hello world!', 'localizationsample');
echo '</p>';
echo '</div>'; // end of wrap
}
(THIS EXAMPLE IS A TRANSLATION to DEUTCH. YOU CAN CHANGE the customs to YOUR DESIRED names.)
in every plugins head, there is an unique name.
(for example:
/*
Plugin Name: my-pluginname
.......
*/
then, in that plugin's folder, create a folder "languages";
then, into your plugin .php file (somewhere in the top), insert the initialization code:
class load_language
{
public function __construct()
{
add_action('init', array($this, 'load_my_transl'));
}
public function load_my_transl()
{
load_plugin_textdomain('my-pluginname', FALSE, dirname(plugin_basename(__FILE__)).'/languages/');
}
}
$zzzz = new load_language;
then open any text editor, then insert like this code (NOTE, THAT we are only adding two sample messages, "hello" and "bye", so , you can ADD AS MANY messages AS YOU WANT with the similar lines).
# English translations for PACKAGE package.
# Copyright (C) 2012 THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# Automatically generated, 2012.
#
msgid ""
msgstr ""
"Project-Id-Version: my-pluginname 1.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-08-06 13:46-0400\n"
"PO-Revision-Date: 2013-03-21 11:20+0400\n"
"Last-Translator: Automatically generated\n"
"Language-Team: none\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"X-Poedit-SourceCharset: iso-8859-1\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 1.5.4\n"
#: mypluginindex.php:87 (it is just a line of a note, to remind where our code appears)
msgid "mymessage1"
msgstr "Hello"
#: mypluginindex.php:88
msgid "mymessage2"
msgstr "Bye"
then save this file as "my-pluginname-en_US.po" (note, that .po is an extension of file, so check that your text editor program has not saved to "my-pluginname-en_US.po.TXT").
then download POEDIT software, and open this file. then edit the "translation" field, and then save as "my-pluginname-de_DE"
there will be generated two files ( If poEdit does not generate the second .mo file automatically, just go to File -> Preferences -> Editor and check the box that says "Automatically compile .mo file on save"),
then put those two file into "languages" folder.
after this, open wp-config.php and find this code:
define ('WPLANG, '');
and change to
define ('WPLANG, 'de_DE');
thats all.
when wordperss is loaded, it will read your plugins language file, with prefix -de_DE.
so, in the plugin's .php file, instead of:
echo "Something string";
you should use:
echo __("mymessage1", 'my-pluginname');
Finished. Now you should test your plugin.
p.s.used links:
https://codex.wordpress.org/I18n_for_WordPress_Developers
http://codex.wordpress.org/Translating_WordPress
https://codex.wordpress.org/Writing_a_Plugin
http://codex.wordpress.org/Installing_WordPress_in_Your_Language
Related
I'm adding a new section to a wordpress site developed by others and based on a child theme of a purchased theme.
To do this, I added the instruction at the bottom of functions.php:
require_once('my_functions.php');
Inside my_functions.php there is a hook to load the text domain used by all my texts, that is, sandbox:
if (!function_exists('mySandobxSetup')) {
function mySandboxSetup() {
if ( is_user_logged_in() ) {
$lang = get_user_meta(get_current_user_id(), 'locale', false);
if ( !empty($lang) ) {
setlocale(LC_ALL, $lang);
}
}
$done = load_child_theme_textdomain('sandbox', get_stylesheet_directory() . '/languages');
log_rec("load_child_theme_textdomain",
"user", get_current_user_id(),
"done", $done,
"TEST", __("Click here to work with your development plan", 'sandbox')
);
}
}
add_action('after_setup_theme', 'mySandboxSetup');
I use a function of mine called log_rec to register a record in log.txt file.
Note that in the child theme directory there is a folder called languages that contains it_IT.po and .mo files.
When I load a single page out of my section, and I logged in by using credentials associated to a user who set his preferred language as it_IT (Italian), I get the following:
▶"load_child_theme_textdomain"■"user"■303■"done"■true■"TEST"■"Clicca qui per lavorare con il tuo piano di sviluppo"■
▶"load_child_theme_textdomain"■"user"■303■"done"■false■"TEST"■"Click here to work with your development plan"■
▶"load_child_theme_textdomain"■"user"■303■"done"■true■"TEST"■"Clicca qui per lavorare con il tuo piano di sviluppo"■
It looks like:
mySandoxSetup is called three times
the first time the load works, the second does not, the third works again
BUT when I look at the page, I see the texts in English and not in Italian as expected.
I browsed the whole site code searching for other *_textdomain() function, but there are none, so I am the only one to load a text domain.
So I have two questions:
what could make that function to be called three times,
why Italian text is not shown in page (where I use __("my text", , 'sandbox'), of course), even if the last call loaded the right text domain?
i have created a plugin "translation_test" to test the translation capabilities of wordpress.
Translation files
in the languages directory there is a file translation_test.pot that contains:
msgid "Testing"
msgstr ""
and a file translation_test-de_DE.po:
msgid "Testing"
msgstr "Das ist ein test"
using gettext i have created the corresponding .mo file with this command:
msgfmt translation_test-de_DE.po -o translation_test-de_DE.mo
i have uploaded all 3 files to the plugin's languages directory: ./translation_test/languages/
Plugin php file:
there is also an php file called "translation_test" where the textdomain is loaded and an admin page created to display the translated text:
<?php
/*
Plugin Name: translation_test
Plugin URI:
Description: translation_test
Version: 1.0
Author:
Author URI:
Text Domain: translation_test
*/
function translation_test_init_textdomain()
{
load_plugin_textdomain( 'translation_test', false, dirname( plugin_basename( '__FILE__' ) ) . '/languages/' );
}
add_action( 'init', 'translation_test_init_textdomain' );
/**
* Register a custom menu page.
*/
function wpdocs_register_my_custom_menu_page(){
add_menu_page( 'title','custom menu','manage_options','custompage','my_custom_menu_page','',6 );
}
add_action( 'admin_menu', 'wpdocs_register_my_custom_menu_page' );
function my_custom_menu_page()
{
echo __( 'Testing', 'translation_test' );
}
?>
Language setting
in the admin area of wordpress i set the language to german and additionally i added the following line to the wp-config.php file:
define ('WPLANG', 'de_DE');
sadly the translation does not work and it always shows "Testing". does anyone know where the error is? is there some bare-bones plugin template that has a working translation that i could use a starting point?
if you're not making a plugin or theme, you're just loading wp-load.php into your application, try doing it this way. Try this:
//get User Locale
$user_locale = get_user_locale();
// load text domain and .mo file
load_textdomain('your_text_domain', $_SERVER['DOCUMENT_ROOT'].'/wp-content/plugins/your_plugin/your_text_domain-'.$user_locale.'.mo');
// function to use with locale hook
function wpsx_redefine_locale($locale){
global $user_locale;
if ($user_locale == ''){
return "en_US";
} else {
return $user_locale;
}
}
// define locale hook
add_filter('locale','wpsx_redefine_locale',10);
// test translation
echo __('test','your_text_domain');
Obs:
I use LOCO translate to manage my text domains and .mo and .po files. https://br.wordpress.org/plugins/loco-translate/
I am using the Profile Builder Pro Plugin to let users upload files to Wordpress. So the files get uploaded to the standard Wordpress upload folder.
However I need to change the upload directory to a subfolder of the uploads folder, but only if the files are uploaded from a certain front end page.
Is there a way I can do this?
Here is the example I use when uploading my custom avatars. Basically you need to add a filter when wp_handle_upload is executed and remove it afterwards, you will also need to add your conditions and generally complete the code to handle posted files, attach them to user or post etc.
//UPLOAD FOLDER FILTER FOR AVATAR
function avatar_upload_dir( $dirs ) {
$dirs['subdir'] = '/avatars';
$dirs['path'] = $dirs['basedir'] . '/avatars';
$dirs['url'] = $dirs['baseurl'] . '/avatars';
return $dirs;
}
//SOME CUSTOM UPLOAD FUNCTION
function somefunction() {
//some code here
add_filter( 'upload_dir', 'avatar_upload_dir' );
$uploaded_file = wp_handle_upload( $data['file'], array( 'test_form' => false ) );
remove_filter( 'upload_dir', 'avatar_upload_dir' );
//some code here
}
You can create new folder media in wordpress directory, then edit the wp-config.php file and this line before
define('UPLOADS', 'media');
/*Thats all, stop editing!, Happy blogging*/
For more detail check this link
I am writing a plugin that will take advantage of other plugin's features (think about a plugin for a plugin).
My file lies in /plugins/new-plugin/new-plugin.php
and I need to make a
include(/plugins/OLD_plugin/old-plugin.php)
so I can use a couple of functions from the old-plugin.php file.
What is the correct way to do this? I could maybe make the functions in old-plugin.php available globally, but I don't want to change the old-plugin.php file.
I've already tried several ways to do this, but none worked. The new-plugin will only show some info in an options page, not viewable for the general public and does not interact with any public page or post in my site.
I've already tried $_SERVER, WP_PLUGIN_DIR, WP_CONTENT_DIR, the absolute server path, relative paths and even some black magic, but nothing seems to work good.
With some of this solutions the plugin's options page shows good but the blog's pages do not render. With other solutions the inverse happens, and with some other solutions nothing even render, be it admin pages or blog's pages, all with errors regarding to file not found.
The new-plugin.php is as simple as
<?php
/*
WP Common Headers
*/
global $wpdb;
if ( ! defined( 'WP_CONTENT_DIR' ) )
define( 'WP_CONTENT_DIR', ABSPATH . 'wp-content' );
if ( ! defined( 'WP_PLUGIN_DIR' ) )
define( 'WP_PLUGIN_DIR', WP_CONTENT_DIR . '/plugins' );
include '/server-absolute-path/public_html/gameblogs/wp-content/plugins/old-plugin/old-plugin.php';
add_action('admin_menu', 'new_plugin_menu');
function new_plugin_menu() {
$page_title = 'New Plugin';
$menu_title = 'New Plugin';
$function = 'new_plugin_admin_page';
$menu_slug = 'new_plugin';
add_menu_page($page_title, $menu_title, 0, __FILE__, $function);
}
function new_plugin_admin_page() {
$result = old_plugin_link_data(" WHERE link_destination NOT LIKE '/%' AND link_destination NOT LIKE '%gameblogs%'");
$total = count($result);
old_plugin_list_links($result, $total, FALSE, FALSE);
*/
}
?>
thanks for any ideas!
check the old plugin files and see if there are any do_actions or apply_filters in it. If there are then you can hook into the old plugin script with your new plugin using add_action and apply_filters and execute other things you want to do.
see http://codex.wordpress.org/Function_Reference/do_action
and http://codex.wordpress.org/Function_Reference/apply_filters
For example (very basic example):
If in old plugin you find a:
do_action('some_type_of_reference);`
In your new plugin you can hook into it by doing:
`add_action('some_type_of_reference', 'name_of_my_function');
function name_of_my_function() {
//executed code here
}`
If in old plugin you find a:
apply_filters('some_type_of_reference', $variable);
Then in your new plugin you can hook into the filter by doing:
apply_filter('some_type_of_reference', 'my_function');
function my_function( $variable ) {
//act on the variable from the filter.
return $variable;
}
Have you looked at the plugins_url function? I haven't had an in-depth read through your code, but it might help.
The plugins_url template tag retrieves the url to the plugins directory or to a specific file within that directory. You can hardcode the plugin slug in $path or pass FILE as a second argument to get the correct folder name.
Hope this helps!
At my website there is "Login or register to post comments.."
I want to change the message to:
"Login or register to post comments(comments will be moderated).."
Because plenty of spammers are just creating logins to post spam comments.
Although all comments are moderated now. Putting this message will give clear info that spamming may not be possible and spammers will not create logins.
Assuming you are using Drupal 6, the code that creates the comment form is in the file comments.module in the Drupal module directory. Fortunately, the function allows for theming.
What you can do is copy and paste the function theme_comment_post_forbidden($node) and place it in the template.php file in your theme directory. You will also need to rename the function, replacing 'theme' with your theme name.
For example, say your theme name is 'utilitiesindia'. Then you will rename your function to utilitiesindia_comment_post_forbidden.
So, in your template.php file in a theme named utilitiesindia, use this function:
/**
* Theme a "you can't post comments" notice.
*
* #param $node
* The comment node.
* #ingroup themeable
*/
function utiltiesindia_comment_post_forbidden($node) {
global $user;
static $authenticated_post_comments;
if (!$user->uid) {
if (!isset($authenticated_post_comments)) {
// We only output any link if we are certain, that users get permission
// to post comments by logging in. We also locally cache this information.
$authenticated_post_comments = array_key_exists(DRUPAL_AUTHENTICATED_RID, user_roles(TRUE, 'post comments') + user_roles(TRUE, 'post comments without approval'));
}
if ($authenticated_post_comments) {
// We cannot use drupal_get_destination() because these links
// sometimes appear on /node and taxonomy listing pages.
if (variable_get('comment_form_location_'. $node->type, COMMENT_FORM_SEPARATE_PAGE) == COMMENT_FORM_SEPARATE_PAGE) {
$destination = 'destination='. rawurlencode("comment/reply/$node->nid#comment-form");
}
else {
$destination = 'destination='. rawurlencode("node/$node->nid#comment-form");
}
if (variable_get('user_register', 1)) {
// Users can register themselves.
return t('Login or register to post comments(comments will be moderated)', array('#login' => url('user/login', array('query' => $destination)), '#register' => url('user/register', array('query' => $destination)))
);
}
else {
// Only admins can add new users, no public registration.
return t('Login to post comments', array('#login' => url('user/login', array('query' => $destination))));
}
}
}
}
how to change the comment link text " Login or register to post comment" to be shorter ,eg " comment"
Also you can use String overrides module.
In Drupal 6:
Another option is to create a small custom module. This uses hook_link_alter(). This is a small example module to change the title of the "Login to post new comment" link: (Replace every instance of MYMODULE_NAME with the name you choose for the module)
STEP 1: Create a file called MYMODULE_NAME.info and add:
; $Id$
name = "MYMODULE_NAME"
description = "Change the appearance of links that appear on nodes"
core = 6.x
STEP 2: Create file called MYMODULE_NAME.module and add:
<?php
// $Id$;
/**
* Implementation of hook_link_alter
*/
function MYMODULE_NAME_link_alter(&$links, $node){
if (!empty($links['comment_forbidden'])) {
// Set "Login to post new comment" link text
$links['comment_forbidden']['title'] = 'NEW TEXT';
// Add this to allow HTML in the link text
$links['comment_forbidden']['html'] = TRUE;
}
}
STEP 3: Put these files in a folder called MYMODULE_NAME, place the folder in sites/all/modules, and enable the module
If you actually want to stop spammers from creating accounts, you should use something like the CAPTCHA module, since they typically use bots that will ignore instructions in any case.
http://drupal.org/project/captcha