From 41dc6adf1f300260662e7890388415bbc3d96aac Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Mon, 12 Nov 2018 17:59:52 +0100 Subject: [PATCH] Use project text domain for translation file names (#107) Extends the `Project` class so that the project's text domain can be stored in the database. The text domain is set whenever translations for a project are updated. It is then used when building language packs, where the text domain is used for the file name of the `.po` und `.mo` files. Fixes #103. --- inc/Project.php | 36 +++++++++++++++++- inc/Updater.php | 5 ++- inc/ZipProvider.php | 15 ++++++-- .../data/example-with-composer/composer.json | 2 +- tests/phpunit/tests/Configuration.php | 2 +- tests/phpunit/tests/Updater.php | 5 ++- tests/phpunit/tests/ZipProvider.php | 38 +++++++++++++++++++ 7 files changed, 93 insertions(+), 10 deletions(-) diff --git a/inc/Project.php b/inc/Project.php index f29e998f..a378c271 100644 --- a/inc/Project.php +++ b/inc/Project.php @@ -85,10 +85,19 @@ class Project { * * @since 3.0.0 * - * @var string Project repository name meta key. + * @var string Webhook sync secret meta key. */ protected const REPOSITORY_WEBHOOK_SECRET_KEY = '_traduttore_repository_webhook_secret'; + /** + * Text domain meta key. + * + * @since 3.0.0 + * + * @var string Text domain meta key. + */ + protected const TEXT_DOMAIN_KEY = '_traduttore_text_domain'; + /** * GlotPress project. * @@ -363,4 +372,29 @@ public function get_repository_webhook_secret(): ?string { public function set_repository_webhook_secret( string $name ): bool { return (bool) gp_update_meta( $this->project->id, static::REPOSITORY_WEBHOOK_SECRET_KEY, $name, 'project' ); } + + /** + * Returns the project's text domain. + * + * @since 3.0.0 + * + * @return null|string Text domain if stored, null otherwise. + */ + public function get_text_domain(): ?string { + $name = gp_get_meta( 'project', $this->project->id, static::TEXT_DOMAIN_KEY ); + + return $name ?: null; + } + + /** + * Updates the project's text domain. + * + * @since 3.0.0 + * + * @param string $name The new text domain. + * @return bool Whether the data was successfully saved or not. + */ + public function set_text_domain( string $name ): bool { + return (bool) gp_update_meta( $this->project->id, static::TEXT_DOMAIN_KEY, $name, 'project' ); + } } diff --git a/inc/Updater.php b/inc/Updater.php index c9f43e13..5cf1cdd4 100644 --- a/inc/Updater.php +++ b/inc/Updater.php @@ -119,8 +119,7 @@ public function update( Configuration $config ) : bool { } $translations = new PO(); - - $result = $translations->import_from_file( $pot_file ); + $result = $translations->import_from_file( $pot_file ); unlink( $pot_file ); @@ -128,6 +127,8 @@ public function update( Configuration $config ) : bool { return false; } + $this->project->set_text_domain( sanitize_text_field( $translations->headers['X-Domain'] ) ); + $stats = GP::$original->import_for_project( $this->project->get_project(), $translations ); /** diff --git a/inc/ZipProvider.php b/inc/ZipProvider.php index 629e6800..a75411d3 100644 --- a/inc/ZipProvider.php +++ b/inc/ZipProvider.php @@ -119,22 +119,29 @@ public function generate_zip_file() : bool { } /* @var GP_Locale $locale */ - $locale = GP_Locales::by_slug( $this->translation_set->locale ); - $project = GP::$project->get( $this->translation_set->project_id ); - $entries = GP::$translation->for_export( $project, $this->translation_set, [ 'status' => 'current' ] ); + $locale = GP_Locales::by_slug( $this->translation_set->locale ); + $gp_project = GP::$project->get( $this->translation_set->project_id ); + $entries = GP::$translation->for_export( $gp_project, $this->translation_set, [ 'status' => 'current' ] ); if ( ! $entries ) { return false; } $files_for_zip = []; + $project = new Project( $gp_project ); + $text_domain = $project->get_text_domain(); /* @var GP_Format $format */ foreach ( [ GP::$formats['po'], GP::$formats['mo'] ] as $format ) { $file_name = str_replace( '.zip', '.' . $format->extension, $this->get_zip_filename() ); + + if ( $text_domain ) { + $file_name = $text_domain . '.' . $format->extension; + } + $temp_file = wp_tempnam( $file_name ); - $contents = $format->print_exported_file( $project, $locale, $this->translation_set, $entries ); + $contents = $format->print_exported_file( $gp_project, $locale, $this->translation_set, $entries ); $wp_filesystem->put_contents( $temp_file, $contents, FS_CHMOD_FILE ); diff --git a/tests/phpunit/data/example-with-composer/composer.json b/tests/phpunit/data/example-with-composer/composer.json index 3695f166..bd993cdf 100644 --- a/tests/phpunit/data/example-with-composer/composer.json +++ b/tests/phpunit/data/example-with-composer/composer.json @@ -7,7 +7,7 @@ "extra": { "traduttore": { "mergeWith": "foobar.pot", - "textDomain": "foo", + "textDomain": "baz", "exclude": [ "bar", "bar/baz.php" diff --git a/tests/phpunit/tests/Configuration.php b/tests/phpunit/tests/Configuration.php index 871beae8..19d7a305 100644 --- a/tests/phpunit/tests/Configuration.php +++ b/tests/phpunit/tests/Configuration.php @@ -38,7 +38,7 @@ public function test_get_config_composer(): void { $this->assertEqualSets( [ 'mergeWith' => 'foobar.pot', - 'textDomain' => 'foo', + 'textDomain' => 'baz', 'exclude' => [ 'bar', 'bar/baz.php', diff --git a/tests/phpunit/tests/Updater.php b/tests/phpunit/tests/Updater.php index caf771cd..b2ceb7fc 100644 --- a/tests/phpunit/tests/Updater.php +++ b/tests/phpunit/tests/Updater.php @@ -52,6 +52,7 @@ public function test_update_without_config(): void { $this->assertTrue( $result ); $this->assertNotEmpty( $originals ); + $this->assertSame( 'foo-plugin', $this->project->get_text_domain() ); } public function test_update_with_composer_config(): void { @@ -63,10 +64,11 @@ public function test_update_with_composer_config(): void { $this->assertTrue( $result ); $this->assertNotEmpty( $originals ); + $this->assertSame( 'baz', $this->project->get_text_domain() ); } public function test_update_with_config_file(): void { - $config = new Configuration( dirname( __DIR__ ) . '/data/example-with-composer' ); + $config = new Configuration( dirname( __DIR__ ) . '/data/example-with-config' ); $result = $this->updater->update( $config ); @@ -74,6 +76,7 @@ public function test_update_with_config_file(): void { $this->assertTrue( $result ); $this->assertNotEmpty( $originals ); + $this->assertSame( 'foo', $this->project->get_text_domain() ); } public function test_has_no_lock_initially(): void { diff --git a/tests/phpunit/tests/ZipProvider.php b/tests/phpunit/tests/ZipProvider.php index 1f751664..d4e1c59d 100644 --- a/tests/phpunit/tests/ZipProvider.php +++ b/tests/phpunit/tests/ZipProvider.php @@ -9,7 +9,9 @@ use GP_Translation_Set; use \GP_UnitTestCase; +use Required\Traduttore\ProjectLocator; use \Required\Traduttore\ZipProvider as Provider; +use ZipArchive; /** * Test cases for \Required\Traduttore\ZipProvider. @@ -223,4 +225,40 @@ public function test_remove_zip_file_no_filesystem(): void { $this->assertFalse( $result ); } + + public function test_use_text_domain_for_translation_files(): void { + $project = ( new ProjectLocator( $this->translation_set->project_id ) )->get_project(); + $original = $this->factory->original->create( [ 'project_id' => $this->translation_set->project_id ] ); + + $this->factory->translation->create( + [ + 'original_id' => $original->id, + 'translation_set_id' => $this->translation_set->id, + 'status' => 'current', + ] + ); + + $project->set_text_domain( 'foo-bar-baz' ); + + $provider = new Provider( $this->translation_set ); + $result = $provider->generate_zip_file(); + + $expected_files = [ 'foo-bar-baz.po', 'foo-bar-baz.mo' ]; + $actual_files = []; + + $zip = new ZipArchive(); + + $zip->open( $provider->get_zip_path() ); + + // phpcs:ignore WordPress.NamingConventions.ValidVariableName.NotSnakeCaseMemberVar + for ( $i = 0; $i < $zip->numFiles; $i ++ ) { + $stat = $zip->statIndex( $i ); + $actual_files[] = $stat['name']; + } + + $zip->close(); + + $this->assertTrue( $result ); + $this->assertEqualSets( $expected_files, $actual_files ); + } }