Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Brian hogg word camp preparing a plugin for translation

227 views

Published on

You have a plugin, but you want users to be able to use it in their native language. Learn how to get it ready for translation, things to watch out for, and tips for maintaining it as you change the plugin over time.

Published in: Technology
  • Be the first to comment

  • Be the first to like this

Brian hogg word camp preparing a plugin for translation

  1. 1. Network: RU-Secure Username: trsguest2017 Password: RUguest253$
  2. 2. Preparing a Plugin for Translation Brian Hogg @brianhogg brianhogg.com
  3. 3. echo esc_html( __( ‘Preparing a Plugin for Translation’, ‘brian-hogg’ ) );
  4. 4. Courses 
 https://brianhogg.com/courses WordCamp Hamilton
 https://hamilton.wordcamp.org/ Plugins
 https://brianhogg.com/plugins Slides https://brianhogg.com/wcto2017/
  5. 5. Who Are You?
  6. 6. Why Translate?
  7. 7. How to Start?
  8. 8. <?php /*** Plugin Name: Event Calendar Newsletter Version: 1.6.1 Author: Brian Hogg Author URI: https://brianhogg.com/ License: GPL2 or later */
  9. 9. <?php /*** Plugin Name: Event Calendar Newsletter Version: 1.6.1 Author: Brian Hogg Author URI: https://brianhogg.com/ License: GPL2 or later Text Domain: event-calendar-newsletter */
  10. 10. Fetch a single event using the ID of that event
  11. 11. __( ’Fetch a single event using the ID of that event’, ‘event-calendar-newsletter’ ); _ _( $string, $textdomain )
  12. 12. __( ’Fetch a single event using the ID of that event’, ‘event-calendar-newsletter’ ); _ _( $string, $textdomain )
  13. 13. __( ’Fetch a single event using the ID of that event’, ‘event-calendar-newsletter’ ); _ _( $string, $textdomain )
  14. 14. __( ’Fetch a single event using the ID of that event’, ‘event-calendar-newsletter’ ); _ _( $string, $textdomain ) Type this out!
  15. 15. // can’t do this define( ‘ECN_TEXT_DOMAIN’, ‘event- calendar-newsletter’ ); // ... __( ’Fetch a single event using the ID of that event’, ECN_TEXT_DOMAIN ); Wrong Way
  16. 16. __( ’Fetch a single event using the ID of that event’, ‘event-calendar-newsletter’ ); Right Way
  17. 17. echo __( ’Fetch a single event using the ID of that event’, ‘event-calendar-newsletter’ ); Outputting the String
  18. 18. _e( ’Fetch a single event using the ID of that event’, ‘event- calendar-newsletter’ ); Outputting the String _e === echo + __
  19. 19. What if you have something you don’t want translated?
  20. 20. Exclude a single event from the listing. Use "current" when using the shortcode on an event page to exclude the current event. Using Placeholders
  21. 21. Exclude a single event from the listing. Use "current" when using the shortcode on an event page to exclude the current event. Using Placeholders
  22. 22. __( ‘Exclude a single event from the listing. Use "current" when using the shortcode on an event page to exclude the current event.’, ‘my-shortcode’ ) Using Placeholders
  23. 23. sprintf( __( ‘Exclude a single event from the listing. Use "%s" when using the shortcode on an event page to exclude the current event.’, ‘my- shortcode’ ), ‘current’ ); Using Placeholders
  24. 24. echo sprintf( __( ‘Exclude a single event from the listing. Use "%s" when using the shortcode on an event page to exclude the current event.’, ‘my- shortcode’ ), ‘current’ ); Using Placeholders
  25. 25. Exclude a single event from the listing. Use "current" when using the shortcode on an event page to exclude the current event. Using Placeholders
  26. 26. What if you want to output HTML?
  27. 27. Can't find the option you're looking for? <a href="https://mysite.com/ support">Submit a support request</a> and we'll do our best to help! Outputting HTML
  28. 28. _e( "Can’t find the option you're looking for? <a href="https://mysite.com/support ">Submit a support request</a> and we'll do our best to help!", ‘my-shortcode’ ); Outputting HTML
  29. 29. _e( "Can’t find the option you're looking for? %sSubmit a support request %s and we'll do our best to help!", ‘my-shortcode’ ); Outputting HTML
  30. 30. echo sprintf( __( "Can’t find the option you're looking for? %sSubmit a support request%s and we'll do our best to help!", ‘my-shortcode’ ), '<a href="https:// mysite.com/support">', ‘</a>' ); Outputting HTML
  31. 31. Avoids link being changed
  32. 32. Avoids broken HTML
  33. 33. Can’t find the option you're looking for? %sSubmit a support request%s and we'll do our best to help!
  34. 34. Sie können die gewünschte Option nicht finden? %sSenden Sie eine Support-Anfrage %s und wir werden unser Bestes tun, um zu helfen!
  35. 35. Sie können die gewünschte Option nicht finden? %sSenden Sie eine Support-Anfrage %s <script>...</script>und wir werden unser Bestes tun, um zu helfen!
  36. 36. esc_html() esc_attr() Escape Functions https://brianhogg.com/tips-sanitizing-validating- wordpress-plugin-data/
  37. 37. esc_html( __( "blah blah blah hahahaha", ‘my-shortcode’ ) ); Escape Functions
  38. 38. esc_html( __( "bla bla bla hihihihi”, ‘my-shortcode’ ) ); Escape Functions
  39. 39. esc_html( __( "bla bla bla <script>alert(‘test’);</ script> hihihihi”, ‘my-shortcode’ ) ); Escape Functions
  40. 40. esc_html( __( "bla bla bla <script>alert(‘test’);</ script> hihihihi”, ‘my-shortcode’ ) ); Escape Functions bla bla bla &lt;script&gt;alert(‘test’);&lt;/ script&gt; hihihihi
  41. 41. Can Combine esc_html/ esc_attr and __/_e Together
  42. 42. esc_html__() esc_html_e() esc_attr__() esc_attr_e() Escape Functions
  43. 43. echo esc_html( __( "blah blah blah hahaha", ‘my-shortcode’ ) ); Escape Functions
  44. 44. echo esc_html( __( "blah blah blah hahaha”, ‘my-shortcode’ ) ); Escape Functions esc_html_e( "blah blah blah hahaha", ‘my-shortcode’ );
  45. 45. echo sprintf( esc_html__( "here is %smy link%s", ‘my-shortcode’ ), ‘<a href=“…”>’, ‘</a>’ ); Careful With sprintf vs esc_html_e( sprintf( __( "here is %smy link%s", ‘<a href="…">’, ‘</a>’ ), ‘my-shortcode’ );
  46. 46. here is my link Careful With sprintf vs here is &lt;a href=“…”&gt;my link&lt;/a&gt;
  47. 47. wp_kses() wp_kses_post() Need HTML?
  48. 48. Plurals
  49. 49. _n( $single_string, $plural_string, $number, $domain ); Plurals
  50. 50. _n( ‘you did one thing’, ‘you did lots of things’, 1, ‘my-plugin’ ); Plurals you did one thing
  51. 51. _n( ‘you did one thing’, ‘you did lots of things’, 5, ‘my-plugin’ ); Plurals you did lots of things
  52. 52. sprintf( _n( ‘you did %s thing’, ‘you did %s things’, $count, ‘my-plugin’ ), $count ); Plurals
  53. 53. What if strings are similar or hard to recognize?
  54. 54. __( ‘Read’, ‘my-plugin’ ); Adding Context __( ‘Read’, ‘my-plugin’ );
  55. 55. _x( $string, $context, $domain ); Adding Context
  56. 56. _x( ‘Event Calendar Newsletter’, ‘Settings title’, ‘my-plugin’ ); Adding Context _x( ‘Event Calendar Newsletter’, ‘Plugin menu title’, ‘my-plugin’ );
  57. 57. date_i18n() Dates
  58. 58. date_i18n( get_option( 'date_format' ), $timestamp ) Dates
  59. 59. JavaScript
  60. 60. wp_localize_script() JavaScript
  61. 61. wp_register_script( ‘ecn_my_script’, plugins_url( ’js/ myscript.js’, __FILE__ ) ); wp_localize_script( ‘ecn_my_script’, ‘ecn_js’, array( ‘success’ => __( ‘You did the thing!’, ‘ecn’ ), ‘failure’ => __( ‘The thing didn’t work’, ‘ecn’ ), ) ); wp_enqueue_script( ‘ecn_my_script’ ); JavaScript https://brianhogg.com/jswp alert( ecn_js.success ); alert( ecn_js.failure );
  62. 62. Don’t trust the strings in JavaScript https://brianhogg.com/tips-sanitizing-validating- wordpress-plugin-data/
  63. 63. Best Practices
  64. 64. Best Practices • Decent English style • Entire sentences • Split at paragraphs • Use format strings instead of string concatenation— sprintf(__('Replace %1$s with %2$s'), $a, $b); is always better than __('Replace ').$a.__(' with ').$b; • Avoid unusual markup and unusual control characters • Do not leave leading or trailing whitespace in a translatable phrase https://codex.wordpress.org/ I18n_for_WordPress_Developers#Best_Practices
  65. 65. Now What?
  66. 66. Now What? • Generate the POT file (base language) • Copy to a PO file (for each translation) • Generate the MO file (compiled for quick string access) • Put them all in the languages/ folder of your plugin https://brianhogg.com/how-wordpress-org-plugin- translations-are-handled/
  67. 67. ... #: core/templates/admin-page.php:2 edd/edd.php:46 msgid "The Events Calendar Shortcode" msgstr "" #: core/templates/admin-page.php:4 msgid "" "The shortcode displays lists of your events. For example the shortcode to " "show next 8 events in the category "%s" in ASC order with date showing:" msgstr "" my-plugin.pot
  68. 68. #: core/templates/admin-page.php:2 edd/edd.php:46 msgid "The Events Calendar Shortcode" msgstr "The Events Calendar Shortcode" #: core/templates/admin-page.php:4 msgid "" "The shortcode displays lists of your events. For example the shortcode to " "show next 8 events in the category "%s" in ASC order with date showing:" msgstr "" "O shortcode mostra listas de seus eventos. Por exemplo, o shortcode para " "mostrar os próximos 8 eventos na categoria "%s", em ordem ASC exibindo a " "data:" my-plugin-pt_BR.po
  69. 69. ??6?I|????dD? ?Z?/! Q,_Y?^?7E:}??UA"?n?O) Ey ? ? ? ? < a@ ? ? ? ?? Xv |? FLE?L?;& -b ? ?? _LZ?^fjm~H??'?V 5w*?&??????vg??]2a ?6?_?V9<?F??e?)?y)k?_o ?(?@?g r????gL??V5S?X?I92? ???j?e?bS????T?!F+h^???83 .l ? /0()2!%3 my-plugin-pt_BR.mo
  70. 70. /languages my-plugin.pot my-plugin-fr_FR.po my-plugin-fr_FR.mo my-plugin-pt_BR.po my-plugin-pt_BR.mo ... Creating the Translations
  71. 71. Creating the POT POEdit https://www.youtube.com/watch?v=s6oRk6nfkI0 makepot.php
 svn co http://develop.svn.wordpress.org/trunk/tools/ grunt-wp-i18n https://github.com/cedaro/grunt-wp-i18n
  72. 72. function my_load_textdomain() { load_plugin_textdomain( ‘my-plugin', false, plugin_basename( dirname( __FILE__ ) ) . '/languages/' ); } add_action( 'plugins_loaded', 'my_load_textdomain' ); Load the Translations
  73. 73. Test by Switching to the Language
  74. 74. Testing
  75. 75. Testing
  76. 76. Maintaining Over Time
  77. 77. Ensure Any New Strings Wrapped in a Translation Function
  78. 78. Automatic POT Generation for wp.org (free) Plugins
  79. 79. Translators Can Pull Requests on github/ bitbucket
  80. 80. DEMO
  81. 81. Takes Work
  82. 82. Questions? Des questions? Questões? ¿Preguntas? Brian Hogg @brianhogg brianhogg.com https://brianhogg.com/wcto2017/

×