cedaro / grunt-wp-i18n

Internationalize WordPress themes and plugins with Grunt.
MIT License
160 stars 25 forks source link

Good way to eliminate duplicates in pot file #73

Open ngocphamm opened 6 years ago

ngocphamm commented 6 years ago

As the title says, I'm trying to find a way to eliminate duplicates in pot file.

The job can be achieved by using msguniq command and I can run it manually in Terminal but I'm wondering if I can do that from within this plugin. I know there is the processPot callback function to play with the resulted pot file, but I'm not quite familiar with how it should work.

Does anyone have experience with this? If yes can you let me know how it should be done?

Thank you all!

bradyvercher commented 6 years ago

Hi @ngocphamm, duplicate strings should already be removed from the generated POT file if your'e using this module. Let me know if you're seeing duplicates after running it, though.

ngocphamm commented 6 years ago

Thanks for super fast response @bradyvercher!

So for now I have this in Gruntfile.js

makepot: {
    plg: {
        options: {
            cwd: '<%= dir.dest %>',
            domainPath: '/languages',               // Where to save the POT file.
            mainFile: '<%= cfg.mainFile %>',        // Main project file.
            potFilename: '<%= cfg.slug %>.pot',     // Name of the POT file.
            type: 'wp-plugin',                      // Type of project (wp-plugin or wp-theme).
            exclude: [],                            // List of files or directories to ignore.
            potHeaders: {
                poedit: true,
                'report-msgid-bugs-to': '<%= cfg.contactLink %>',
                'plural-forms': 'nplurals=2; plural=n != ',
                'last-translator': '<%= cfg.langTeamEmail %>',
                'language-team': '<%= cfg.langTeamEmail %>',
                'x-textdomain-support': 'yes',
                'x-poedit-keywordslist': true
            },
            processPot: null
        }
    }
},

Then the generated pot file has these 2 duplicated entries

#. Plugin Name of the plugin/theme
msgid "My Plugin Name"
msgstr ""

#: class/class-plugin.php:56
msgid "My Plugin Name"
msgstr ""

because of this piece of code, I suppose.

add_action( 'admin_menu', function() {
            add_menu_page(
                __( 'My Plugin Name', 'plg-slug' ),       // Page title.
                __( 'My Plugin Name', 'plg-slug' ), // Menu title.
                'manage_options',
                SETTING_PAGE,
                array( '\MyPlugin\Plugin', 'config_page' ),
                Helper::get_base64_icon(),
                '99.999'
            );
        } );

Should there not be duplicates in this case?

bradyvercher commented 6 years ago

Hmm, I'm not sure about that one.

That first entry is the name of the plugin from the header in your main plugin file.

The second entry comes from that add_menu_page() call, but even though you have two gettext calls there with the same string, those aren't being duplicated.

Deduplication in this module relies on the gettext-parser module, so it may consider something about those strings to be unique. Maybe the presence of a comment for the plugin header entry? The delimiter is different (#. vs #:), so the comment may be serving as context to differentiate the strings.

I haven't looked into this before, so that's all I have for now without digging in deeper.

ngocphamm commented 6 years ago

I think you are right, as the 2 lines for Page title and Menu title don't get duplicates.

But there's probably nothing to do for now. Do you have an idea of how to run the msguniq within processPot method? That could be one way to fix it at this time.

bradyvercher commented 6 years ago

If the header is being disambiguated with context, then even msguniq should treat them as separate strings.

For example, you can try adding a call to _x( 'My Plugin Name', 'context comment', 'plg-slug' ) in one of your plugin files and running the makepot task. You should see a third entry for the same string.

processPot wouldn't be the best place to call msguniq if you wanted to go down that road. That callback lets you work with the POT object in JavaScript before it's serialized into a POT file. You would want to wait until after the makepot task had completed before running msguniq against the generated POT file.

If you really want to remove the plugin header, this example should help.

ngocphamm commented 6 years ago

I ran msguniq against the resulted pot file and it did merge the entries so I guess it works.

Thanks for the example! I will look around for some more info. I really appreciate your help!

bradyvercher commented 6 years ago

Thanks for letting me know about msguniq merging them and keep me updated if you discover anything new!

ngocphamm commented 6 years ago

So now I have a separate task, which will be executed after makepot to make sure the pot file will only have unique msgids.


        exec: {
            potunique: {
                expand: true,
                cwd: '<%= dir.dest %>/languages',
                cmd: '/usr/local/bin/msguniq <%= cfg.slug %>.pot -o <%= cfg.slug %>.pot'
            }
        }```