28th Sep2016

Prevent duplicate Drafts, Junk, Sent, Trash folders in Dovecot

by Gyro

I've set up a new mail server for a client, and then used imapsync to copy all existing mail from the old server to the new server.

Everything seemed to have run smoothly, but shortly after they started using email via the new server, they had multiple folders for drafts, junk, sent, and trash.

After investigating this a bit, I found out that different mail clients expect different folder names on the server, and dovecot will create them when missing.

This really confused me, as this was not happening on the old server, so why was this now happening on the new server?!

Well, I could have prevented this from happening, if I would have had a look at the old server's configuration.

Turns out, you have to configure "Namespaces" to properly configure folders and possible duplicates.

Below is the configuration that was (and now is) in place. It has to be added to /etc/dovecot/dovecot.conf


namespace inbox {
  type = private
  separator = .
  prefix = INBOX.
  inbox = yes

  mailbox Drafts {
    special_use = \Drafts
    auto = subscribe
  }

  mailbox Junk {
    special_use = \Junk
    auto = create
  }

  mailbox spam {
    special_use = \Junk
    auto = no
  }

  mailbox Spam {
    special_use = \Junk
    auto = no
  }

  mailbox Trash {
    special_use = \Trash
    auto = subscribe
  }

  mailbox Sent {
    special_use = \Sent
    auto = subscribe
  }

  mailbox Sent Mail {
    special_use = \Sent
    auto = no
  }

  mailbox "Sent Messages" {
    special_use = \Sent
    auto = no
  }

  mailbox Archive {
    special_use = \Archive
    auto = create
  }

  mailbox "Archives" {
    special_use = \Archive
    auto = no
  }
}

With this configuration you get this setup:

INBOX
INBOX.Drafts
INBOX.Junk
INBOX.Trash
INBOX.Sent

Meaning, the Drafts, Junk, Trash, and Sent folders will reside inside the Inbox. Mail clients wanting to be different will have their special folder names mapped to the "one and only" folder of that type, such as iPhone's "Sent Messages" being the actual "Sent" folder.

I hope this helps anyone facing the same issue. Please leave a comment, if you found another special folder name that should be added to this list.

Enjoy! :)

185

26th Sep2016

Load ISPConfig on subdomain using website’s ssl certificate

by Gyro

I've spent the last few days installing and configuring ISPConfig 3.1 on a new server, and one thing I really don't like about ISPConfig is the custom port it is running on.

So, I thought it would be really cool to use a subdomain instead and forget about the port all together.

It took me quite a while to figure out how to make ISPConfig load on a subdomain and have the subdomain configured for each website automatically. Of course I googled it, but information on how to accomplish this is quite rare (non-existent?), and I had to take stuff from a few different sources to come up with the (in my opinion) perfect solution.

The result: ISPConfig loads on an automatically configured subdomain and even works with each website's ssl certificate!

EDIT: This approach currently does not work with letsencrypt, because letsencrypt does not create a SSL certificate including the subdomain used for ISPConfig, so your browser willl warn you about an invalid SSL certicate being used. I am working on a solution. If you have a wildcard SSL certificate from a different vendor, this will work though.

Prerequisite

1. Make sure the following mods are enabled
~$ sudo a2enmod proxy_http
~$ sudo a2enmod proxy

2. You have to activate SSL for each website
A self-signed SSL certificate is sufficient, but I recommend getting a free one from StartSSL or LetsEncrypt.
ISPConfig 3.1+ can automatically setup a valid LetsEncrypt SSL certificate for each website.

Modify Vhost Master Template

~$ sudo nano /usr/local/ispconfig/server/conf/vhost.conf.master

Add the following code directly under </VirtualHost>, near the bottom of the file.

This will only work with https, and it will redirect http to https


#--------------------------------------------
# START: Add ISPConfig subdomain to all accounts
#--------------------------------------------
<tmpl_if name='ssl_enabled'>
<VirtualHost {tmpl_var name='ip_address'}:{tmpl_var name='port'}>
ServerName panel.{tmpl_var name='domain'}
SSLProxyEngine On
SSLProxyVerify none
SSLProxyCheckPeerCN off
SSLProxyCheckPeerName off
SSLProxyCheckPeerExpire off
ProxyVia off
ProxyRequests off
ProxyPreserveHost on
ProxyPass / https://localhost:1155/
ProxyPassReverse / https://localhost:1155/
</VirtualHost>
<tmpl_else>
# Redirect unsecure to secure connection
<VirtualHost {tmpl_var name='ip_address'}:{tmpl_var name='port'}>
ServerName panel.{tmpl_var name='domain'}
Redirect 301 / https://panel.{tmpl_var name='domain'}/
</VirtualHost>
</tmpl_if>
#--------------------------------------------
# END: Add ISPConfig subdomain to all accounts
#--------------------------------------------

This will work with both -- http and https conections


#--------------------------------------------
# START: Add ISPConfig subdomain to all accounts
#--------------------------------------------
<tmpl_if name='ssl_enabled'>
<VirtualHost {tmpl_var name='ip_address'}:{tmpl_var name='port'}>
ServerName panel.{tmpl_var name='domain'}
SSLProxyEngine On
SSLProxyVerify none
SSLProxyCheckPeerCN off
SSLProxyCheckPeerName off
SSLProxyCheckPeerExpire off
ProxyVia off
ProxyRequests off
ProxyPreserveHost on
ProxyPass / https://localhost:1155/
ProxyPassReverse / https://localhost:1155/
</VirtualHost>
<tmpl_else>
<VirtualHost {tmpl_var name='ip_address'}:{tmpl_var name='port'}>
ServerName panel.{tmpl_var name='domain'}
SSLProxyEngine On
SSLProxyVerify none
SSLProxyCheckPeerCN off
SSLProxyCheckPeerName off
SSLProxyCheckPeerExpire off
ProxyVia off
ProxyRequests off
ProxyPreserveHost on
ProxyPass / https://localhost:1155/
ProxyPassReverse / https://localhost:1155/
</VirtualHost>
</tmpl_if>
#--------------------------------------------
# END: Add ISPConfig subdomain to all accounts
#--------------------------------------------

Notes

1. You have to change the port (1155) to match the port that your ISConfig installation runs on (default is 8080).
2. You may want to replace "panel" with a different word for the subdomain.

Enjoy! :)

386

06th May2016

WP Lightbox stopped working – jQuery version the culprit.

by Gyro

I just spent a while trying to figure out why a lightbox stopped working on a friend's WP site.

Supposedly nothing had changed… and looking at the code, everything looked ok.

After some trial and error, I finally figured out that the issue was with the jQuery version, the site was loading version 1.2.1, which apparently does not work with the lightbox plugin. I tried jQuery version 2.0.2, but that seems to have been too much, so I finally settled on jQuery version 1.7.1 which seem to work well with any jQuery script junning on his site.

An easy way to manually set this jQuery version in WordPress is adding some code to the theme's functions.php:

function modify_jquery_version() {
if (!is_admin()) {
wp_deregister_script(‘jquery');
wp_register_script(‘jquery', ‘http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js', false, ‘1.7.1');
wp_enqueue_script(‘jquery');
}
}
add_action(‘init', ‘modify_jquery_version');

Just change the version numbers 1.7.1 to the one you need.

32

29th May2015

Report to New Relic APM on cPanel/CloudLinux with CageFS

by Gyro

I finally found out how to get PHP apps hosted on a cPanel server with CloudLinux and CageFS enabled to report to New Relic APM.

Since I spent days searching and trying, with giving up on several occasions, I figured this definitely deserves a post on my blog.

So, how did I manage to have apps report to new relic for ALL enabled cagefs users, and them being able to use their own new relic license/account?

Well, the problem was the default settings for the socket. The socket was simply not available for cagefs users being in the /tmp folder.

Login via ssh and check /tmp as root and as a user, and you will see that .newrelic.socket is missing for the users (~$ ll /tmp)

AFAIK this is due to cagefs creating "fake" /tmp directories for each user, for example you will see all the sessions of a user only in the /tmp of the user, but not in the physical /tmp of the server's fileystem.

To get around this, I did the following:

1. I created the folder /var/run/newrelic-global/ (not sure if it was necessary)

2. I added the following lines in /etc/newrelic/newrelic.cfg:

pidfile = "/var/run/newrelic-global/newrelic-daemon.pid"
port = "/var/run/newrelic-global/.newrelic.sock"

3. I added the following line in /etc/cagefs/cagefs.mp:

/var/run/newrelic-global

After that I ran these commands:
~$ /etc/init.d/newrelic-daemon restart
~$ cagefsctl --remount-all

Now, users can either define the php flags via .htaccess (if possible), or configure their own php.ini (if available), depending on how the server has been configured and/or what their preferences are. Below the example of what to do in the .htaccess file.

<IfModule mod_php5.c>
php_value newrelic.daemon.port "/var/run/newrelic-global/.newrelic.sock"
php_value newrelic.daemon.pidfile "/var/run/newrelic-global/newrelic-daemon.pid"
php_value newrelic.license "MyNewRelicLicense"
php_value newrelic.appname "MyAppName"
</IfModule>

To check, if it is working, have a look at the log file (Default location is: /var/log/newrelic/newrelic-daemon.log). You should see something like this:


…info: [‘MyAppName'] ‘Reporting to:…

Before all this, you should of course install the php agent:
https://docs.newrelic.com/docs/agents/php-agent/installation/php-agent-installation-redhat-centos
It will ask to update the php.ini during the installation of the agent. Select the one located in /usr/local/lib.
Once the installation is completed, run ~$ cagefsctl --force-update (those are 2 dashes infront of force-update).

Also, you may want to have a look at this page, if you are using the newrelic-sysmond daemon to monitor your server.
https://www.lucasrolff.com/cpanel/new-relic-and-cloudlinux/

Enjoy :)

1012

06th May2015

Simple “Are you sure?” warning for unsaved changes in WP

by Gyro

I spent quite a few hours getting a seemingly simple piece of javascript to work in a WP plugin I am currently working on.

Naturally, I started with jquery as it is already included in the WP Admin, but after several hours of trying various solutions I found on the web I had to admit defeat. I just could not get it to work the same way it obviously worked for others using jquery.

So, I ended up looking around a bit to find all natural javascript to do this.

function myplugin_js() {
echo ' <script>
window.onload = function(){
var theform = document.myform;
window.onbeforeunload = function(e){
var e = e || window.event, simon = "go";
for (i=0; i<theform.elements.length; i++){
if(theform.elements[i].type == "radio" || theform.elements[i].type == "checkbox"){
if(theform.elements[i].checked != theform.elements[i].defaultChecked){simon = "no";}
}else if(theform.elements[i].type == "select-one"){
if(!theform.elements[i].options[theform.elements[i].selectedIndex].defaultSelected){simon = "no";}
}else if(theform.elements[i].type == 'submit'){
theform.elements[i].onmouseup=function(){
simon = 'go';
}
}else{
if(theform.elements[i].value != theform.elements[i].defaultValue){simon = "no";}
}
}
if(simon != "go"){if(e){e.returnValue = "unsaved chages detected";}return "unsaved chages detected";}
}
};
</script>';
}
add_action('admin_enqueue_scripts', 'myplugin_js');

You can put this in a theme functions.php or in your plugin file.

This will cause a warning message to popup whenever the form with the name "myform" was modified and one attempts to load a new page.

Change ‘admin_enqueue_scripts' to ‘wp_enqueue_scripts' to enable this feature on the front-end of your website.

If you use a select element, make sure you have a default option "selected", else the script will fail.

Enjoy :crazy:

Sources:

271

28th Apr2015

Unable to connect to github.com using git://github.com

by Gyro

While installing boostrap-sass using bower, the server returned a weird error message.

Failed to execute "git ls-remote --tags --heads git://github.com/twbs/bootstrap-sass.git", exit code of #128 fatal: unable to connect to github.com: github.com[0: 192.30.252.130]: errno=Connection timed out

I was a bit confused as this was working perfectly fine on my localhost, after some searching I found out that "The native git protocol uses port 443 for the main repo and port 9418 for the submodules. If this port is firewalled on the network, recursive clone times out and fails.".

Git can use https:// instead of git://, so the solution is to set it to use https:// by default:

~$ git config --global url."https://".insteadOf git://

Enjoy :crazy:
Gyro

 

Sources:
https://github.com/lagadic/vision_visp/issues/13
https://github.com/angular/angular-phonecat/issues/141

 

Similar error messages:

  • fatal: unable to connect to github.com:
    github.com[0: 192.30.252.131]: errno=Connection timed out
    Clone of ‘git://github.com/lagadic/visp_auto_tracker.git' into submodule path ‘visp_auto_tracker' failed
  • npm ERR! Error: Command failed: fatal: unable to connect to github.com:
    npm ERR! github.com[0: 192.30.252.130]: errno=Connection timed out
  • Failed to execute "git ls-remote --tags --heads git://github.com/twbs/bootstrap-sass.git", exit code of #128 fatal: unable to connect to github.com: github.com[0: 192.30.252.130]: errno=Connection timed out
    fatal: unable to connect to github.com:
    github.com[0: 192.30.252.130]: errno=Connection timed out

2126

09th Feb2015

SEO Best Practice: Subdomains or Sub-folders?

by Gyro

When to use Subdomains or Subfolders for better SEO

I follow moz quite a lot, and there is an article that made me think a lot.

5. Subdomains or Sub-folders
Since search engines keep different metrics for domains than they do subdomains, it is recommended that webmasters place link-worthy content like blogs in subfolders rather than subdomains. (i.e. www.example.com/blog/ rather than blog.example.com) The notable exceptions to this are language-specific websites. (i.e., en.example.com for the English version of the website).

This discussion on moz gave an interesting insight as to why moz thinks subfolders are better than subdomains. The first comment is from a moz-staffer:

"We recently were able to test this using a subdomain on Moz itself (when moving our beginner's guide to SEO from guides.moz.com to the current URL http://moz.com/beginners-guide-to-seo). The results were astounding -- rankings rose dramatically across the board for every keyword we tracked to the pages."

Now, consider what Matt Cutts once said:

"A subdomain can be useful to separate out content that is completely different.".

My theory/understanding:

Before moz's move from subdomain to subfolder, google considered their guides as "completely different" content from the content on moz.com. Another factor is that a subdomain has its own PR and DA, so by moving the guides into the main domain, it shared the PR and DA of moz.com and also improved moz.com itself by giving it more pages with relevant content.

My conclusion:

1. If you want to install a blog on your domain with content that is related to your main site, you should put it in a subfolder, so blog and site benefit from each other.

2. If you want to install a blog on your domain with content that is unrelated to your main site, it would make sense to install it on a subdomain, rather than a subfolder.

What do you think?

:)

p.s. I originally posted this in a forum and got an amazing 18 views in 2 months… let's see how many people end up reading it here :)

585

30th Dec2014

PHP Perfection: Ajax Image Upload Script

by Gyro

Today I stumbled upon a neat little PHP image upload script that includes the html/js front-end script to easily upload images. The script displays a simple upload form, you select an image from your computer, click on upload, and the script uploads the image via php. Once the image has been uploaded, a thumbnail will be displayed in place of the upload form and button. The script can be easily implemented into any existing code and customization is also no problem for anyone with some html/js/php expience.

For me, it's simply perfect :)

 

519

08th Aug2014

Best way to manipulate images using PHP?

by Gyro

I have deployed lots of different solutions to manipulate images with PHP, but today I stumbled upon probably the best PHP library out there.

It is called WideImage (requires PHP 5.2+ with GD2 extension), and it makes resizing, cropping, rotating, adding watermarks. and much more super easy.

Check out WideImage, I'm sure you'll love it!

Enjoy! :crazy:

712

06th Aug2014

Comming Soon: HHVM Support in WHM/cPanel?

by Gyro

Great news everyone, it looks like cPanel is gearing up to integrate HHVM (HipHip Virtual Machine)!

I just received a notification from the official features request section of cPanel, in particular the request for PHP HHVM support for better performance.

To quote: "Has anyone had any success implementing PHP HHVM on their own? It's very helpful for us to hear about real world experiences with features we are considering to add in cPanel & WHM." -- cPScottT (cPanel staff).

Don't know HHVM yet?

HHVM is what powers Facebook, it has been developed by Facebook, and they made it available for everyone free of charge. HHVM processes PHP code lighting fast and is currently compatible with about 98% of all php applications.

Today, cPanel employees have finally picked up on this and started asking some questions about HHVM in the respective feature request. What happened next is what got me really excited: Their entire features request section went temporarilly offline! I can only guess that the news has spread rapidly through the twitterverse and other social media channels, resulting in such an increase of page requests that it overwhelmed their server! Maybe they should run their feature request section on HHVM…

Anyways, I am pretty sure that with this kind of response to an "innocent" question by cPanel staff, integrating HHMV into WHM/cPanel has just jumped to the top of their To-Do-List.

Not sure about you, but I am thrilled about this news! :crazy:

1757

05th Aug2014

Free Styles for Google Maps

by Gyro

Today, I was working on a website that needed a Google map and ran into a real problem: None of the "looks" really fit in the design of the website.

After some searching on how to customize the look of a Google Map, I came across a website that just won my imaginary website of the year award.

It is called Snazzy Maps, a FREE repository of different color schemes for Google Maps aimed towards web designers and developers. All styles are licensed under creative commons and are completely free to use.

Check it out: Free Styles for Google Maps

557

30th Jun2014

Using qTranslate with WordPress 3.9++

by Gyro

I've been a long time fan of Qian Qin's qTranslate plugin, which allows you to translate just about everything you need to have a multilinugal website running on WordPress.

Unfortunately, he seems to have fallen off the face of the earth since WordPress Version 3.9 came out, so installing the plugin will result in its automatic deactivation, as the only available qTranslate version has not been officially tested with any WordPress version newer than WP 3.8.1 :(

I've been waiting for an update for months now, and I have come to the realization that I may have to wait a lot longer. So, I decided to see what I can do with this plugin to make it work again. Turns out, there are two simple file modifications needed in order to make qTranslate work with WordPress 3.9.1, which is the newest WP version that is available while I am writing this post.

If a new WP version is released, come back here to check if this fix/hack still works, BEFORE you update your WP installation.

Should there be a newer version available than WordPress Version 3.9.1, please write a comment. I will reply with a status report asap!

qTranslate WordPress 3.9 Fix

Short Question: So, what is there to do?

Short Answer: You have to modify two files in the /qtranslate/ plugin folder (via ftp).

1. Modify qtranslate.php

change this:

define('QT_SUPPORTED_WP_VERSION', '3.8.1');

to this:
define('QT_SUPPORTED_WP_VERSION', '3.9.1');
which allows activating qTranslate up to WordPress version 3.9.1.

You could also do this:

define('QT_SUPPORTED_WP_VERSION', $wp_version);
which allows activating qTranslate on EVERY new WordPress version. Warning: qTranslate may be incompatible with future WordPress versions and break your website! I highly recommend the first option.

2. Modify qtranslate_core.php

change this:

function qtrans_dateFromPostForCurrentLanguage($old_date, $format ='', $before = '', $after = '') {
global $post;
return qtrans_strftime(qtrans_convertDateFormat($format), mysql2date('U',$post->post_date), $old_date, $before, $after);
}

to this:
function qtrans_dateFromPostForCurrentLanguage($old_date, $format ='') {
global $post;
return qtrans_strftime(qtrans_convertDateFormat($format), mysql2date('U',$post->post_date), $old_date);
}

And that's already all there is to it! :)

Enjoy!

p.s. You may want to add this to your functions.php, it will increase the width of menu items in the admin… these tiny input fields drove me insane! :crazy:

add_action('admin_head', 'my_custom_fonts');
function my_custom_fonts() {
echo '<style>
.menu-item-bar .menu-item-handle {
width: 582px;
}
.description-thin {
width: 550px;
}
.menu-item-settings {
width: 602px;
</style>';
}

Sources:
http://wordpress.org/support/topic/the-qtranslate-editor-has-disabled-itself-because-it-hasnt-been-tested-with-you
http://alexander.kirk.at/2014/04/17/fix-qtranslate-with-wordpress-3-9/
http://css-tricks.com/snippets/wordpress/apply-custom-css-to-admin-area/

1491

21st Feb2013

Speed up your WordPress with CloudFlare!

by Gyro

My web hosting services provider ServerPilot has integrated CloudFlare into the cPanel!

CloudFlare is Content Deliver Network (CDN) with 22 data centers across the globe, and according to google there are only 9 web services in the world that have more traffic than CloudFlare. It is free, and it will make your website's load lightning fast from anywhere in world!

Even if your website is hosted with a slow hosting provider elsewhere, you can use CloudFlare for free!

If you give CloudFlare a try, make sure you also get the CloudFlare WordPress Plugin! WIth it, you can turn on the "Developer Mode" from your WordPress admin panel -- a must when updating your site, as changes won't show up immediately if the Developer Mode is turned off.

Enjoy! :enjoy:

1131

21st Feb2013

Restore large mysql databases with nginx 504 Gateway Timeout

by Gyro

I had to restore a 36MB sql database today and kept getting a "504 Gateway Time-out".

After playing around with the config files, adding fastcgi_read_timeout to the settings for php5-fpm, and fiddling with the php.ini, I realized that this can be accomplished with one single line using ssh:

Assuming that you have packed the .sql file into a zip file, and you are currently in that folder:
# gunzip < databasebackup.sql.gz | mysql -DDATABASENAME -uUSERNAME -pPASSWORD

DATABASENAME = name of the database
USERNAME = mysql username
PASSWORD = mysql password

I hope this helps when trying to restore large mysql databases with nginx 504 Gateway Timeout

2278

11th Feb2013

WHMCS: Round up product prices for secondary currencies

by Gyro

Today, I actually assisted my hosting provider in setting up secondary currencies in WHMCS, the billing and support system for/from cpanel! :)

They only wanted full numbers for the monthly breakdowns, so when they click "Update Prices" in the Currency Settings and a product would cost 1233.37 the price gets automatically rounded up to 1234.00.

Unfortunately, WHMCS doesn't offer this feature, so I suggested to setup a script on a secure location that they can trigger after they update the currency conversion rates and product prices. Below is the sql query that goes through all secondary currencies (1 = default currency) and rounds up the values, so that the setup fee and all monthly prices are full numbers.

The script itself would run a simple MySQL query:

UPDATE tblpricing SET
msetupfee = ceil(msetupfee),
qsetupfee = ceil(qsetupfee),
ssetupfee = ceil(ssetupfee),
asetupfee = ceil(asetupfee),
bsetupfee = ceil(bsetupfee),
tsetupfee = ceil(tsetupfee),
monthly = ceil(monthly),
quarterly = ceil(quarterly/3)*3,
semiannually = ceil(semiannually/6)*6,
annually = ceil(annually/12)*12,
biennially = ceil(biennially/24)*24,
triennially = ceil(triennially/36)*36
WHERE
currency != 1 AND
id = id

you could replace

currency != 1 AND

with
currency = 2 AND

or
currency IN(2,3,6) AND

etc

Enjoy :enjoy:

1896

31st Jan2013

Who is hosting WebDesignBlog.asia?

by Gyro

Webdesignblog.asia is being hosted on a Shared Hosting account from ServerPilot, which includes a Free Domain and loads of other goodies!

ServerPilot offers everything from 99ct hosting to high end dedicated servers for incredibly low prices. The shared hosting servers are running CloudLinux, providing a stable and fast performance for all hosting accounts sharing the server.

Wondering why my websites loads so fast? Do a "dig www.webdesignblog.com", and you will see that this website is actually being served from the CloudFlare CDN, which is integrated into the ServerPilot.com cPanel and FREE!

Be my neighboor, move to ServerPilot! :enjoy:

1030

21st Jan2013

Gitlab service doesn’t run on startup/boot/autostart

by Gyro

I have been using Gitlab for a while now to have backups of all my git repositories on my dedicated servers. Now, I needed to reboot one of them for the first time since I installed Gitlab, and ended up with a ‘502 bad gateway' warning by nginx, when trying to access the Gitlab web interface.

I found this on the github, hidden in a small pull request:

gitlab doesn't start on boot if you follow the install instructions on Ubuntu (12.04 LTS Server -- probably others). Turns out gitlab requires redis-server to be running for gitlab to be able to start. Startup script S20redis-server isn't run until after S20gitlab so gitlab fails to start on boot. Webserver will be up, bad gateway 502 error is usually seen/reported. Starting gitlab manually works (because redis-server has started). This change makes gitlab start after redis-server.

The single line for victory:
# sudo update-rc.d gitlab defaults 70 30

Enjoy :enjoy:

source: github

2396

17th Jan2013

Add customized Google Translate to your website

by Gyro

Google translate has a feature called the Website Translator to help you translate your website.

Here is how it works:

  1. Add your website
  2. Customize the way the Google Translate will look on your website, I usually add a google translate dropdown menu to websites.
  3. Add the custom code to your website.
  4. View your website in another language and click on text that has not been translated to your satisfaction, you will see a popup with the option to submit a translation suggestion. Once a translation suggestion has been submitted, you can review and activate it in the Website Translator

Enjoy :enjoy:

1680

Pages:123»