Make WordPress Core

Opened 6 years ago

Closed 3 weeks ago

#11226 closed task (blessed) (fixed)

Month name declension case

Reported by: waclawjacek Owned by: SergeyBiryukov
Milestone: 4.4 Priority: normal
Severity: minor Version: 2.9
Component: I18N Keywords: has-patch
Focuses: Cc:


As I've reported previously, in order to fully translate WordPress into Polish (and probably many more languages), dates have to be declended. This was fixed in #9396, however proper translation into Polish still cannot be accomplished.

You see, the "January 2009" is something else for

"View posts published in January 2009"

and just

"January 2009"

In the former case, it's a locative. In the latter, it's simply a genitive. What needs to be done in order to fix this is passing some kind of information to the date_i18n filter, informing it of the case.

I suggest passing the declension case information (whether it's genitive, locative or something else). That should do it. :)

Attachments (3)

11226.diff (1.1 KB) - added by Denis-de-Bernardy 6 years ago.
11226.2.diff (1.3 KB) - added by wonderboymusic 2 months ago.
11226.3.diff (5.5 KB) - added by SergeyBiryukov 7 weeks ago.

Download all attachments as: .zip

Change History (35)

#1 @Denis-de-Bernardy
6 years ago

  • Keywords early added
  • Milestone changed from Unassigned to 3.0
  • Type changed from defect (bug) to enhancement
  • Version set to 2.9

Just making sure I'm understanding this right... What you're meaning is that the filter should look something like this?

$string = __('foo %s');
sprintf($string, date_i18(...,$string));

#2 @waclawjacek
6 years ago

Well, I was thinking of passing an adidtional parameter to

        $j = apply_filters('date_i18n', $j, $req_format, $unixtimestamp, $gmt); 

(I don't know how to pass additional parameters to WordPress filter functions), but now when I think of it, the best solution would probably be to translate every occurrence of a month name... That was coders wouldn't have to stuff like some_function( 'declend_stuff', 'locative' );

#3 follow-up: @waclawjacek
6 years ago

... and in the code it'd probably be something similar to

Post published in <?php _e( 'January', 'locative' ); ?>

#4 in reply to: ↑ 3 @Denis-de-Bernardy
6 years ago

Replying to waclawjacek:

... and in the code it'd probably be something similar to

Post published in <?php _e( 'January', 'locative' ); ?>

So we're on the same wavelength... The issue with the above is that "locative" means something for you and I, but there is no such notion in a number of languages. So it's better to pass the original string.

#5 @waclawjacek
6 years ago

Yay, a "context" is a very nice idea. :)

#6 @Denis-de-Bernardy
6 years ago

it will need an huge additional (huge) patch to change all of the calls where date_i18n() gets used though. And such a patch will become stale almost on the spot unless a core dev decides it's interesting, and commits it on the spot.

#7 @nacin
6 years ago

It's 20 references spanning 11 files. It'll get stale, but it won't be a huge patch.

wp-admin/admin-ajax.php:        $message = sprintf( __('Draft Saved at %s.'), date_i18n( $draft_saved_date_format ) );
wp-admin/edit-form-advanced.php:                        $message = sprintf( __('Post scheduled for: <b>%1$s</b>. <a target="_blank" href="%2$s">Preview post</a>'), date_i18n( __( 'M j, Y @ G:i' ), strtotime( $post->post_date ) ), get_permalink($post_ID) );
wp-admin/edit-form-comment.php:$date = date_i18n( $datef, strtotime( $comment->comment_date ) );
wp-admin/edit-page-form.php:                    $message = sprintf( __('Page scheduled for: <b>%1$s</b>. <a target="_blank" href="%2$s">Preview page</a>'), date_i18n( __( 'M j, Y @ G:i' ), strtotime( $post->post_date ) ), get_permalink($post_ID) );
wp-admin/includes/meta-boxes.php:       $date = date_i18n( $datef, strtotime( $post->post_date ) );
wp-admin/includes/meta-boxes.php:       $date = date_i18n( $datef, strtotime( current_time('mysql') ) );
wp-admin/options-general.php:<span id="utc-time"><?php printf(__('<abbr title="Coordinated Universal Time">UTC</abbr> time is <code>%s</code>'), date_i18n( $time_format, false, 'gmt')); ?></span>
wp-admin/options-general.php:   <span id="local-time"><?php printf(__('UTC %1$s is <code>%2$s</code>'), $current_offset_name, date_i18n($time_format)); ?></span>
wp-admin/options-general.php:    <span id="utc-time"><?php printf(__('<abbr title="Coordinated Universal Time">UTC</abbr> time is <code>%s</code>'), date_i18n($timezone_format, false, 'gmt')); ?></span>
wp-admin/options-general.php:   <span id="local-time"><?php printf(__('Local time is <code>%1$s</code>'), date_i18n($timezone_format)); ?></span>
wp-admin/options-general.php:                   printf( $message, date_i18n(get_option('date_format').' '.get_option('time_format'), $tr['ts'] ) );
wp-admin/options-general.php:           echo ' /> ' . date_i18n( $format ) . "</label><br />\n";
wp-admin/options-general.php:   echo '/> ' . __('Custom:') . ' </label><input type="text" name="date_format_custom" value="' . esc_attr( get_option('date_format') ) . '" class="small-text" /> ' . date_i18n( get_option('date_format') ) . "\n";
wp-admin/options-general.php:           echo ' /> ' . date_i18n( $format ) . "</label><br />\n";
wp-admin/options-general.php:   echo '/> ' . __('Custom:') . ' </label><input type="text" name="time_format_custom" value="' . esc_attr( get_option('time_format') ) . '" class="small-text" /> ' . date_i18n( get_option('time_format') ) . "\n";
wp-includes/default-widgets.php:                                        $date = ' <span class="rss-date">' . date_i18n( get_option( 'date_format' ), $date_stamp ) . '</span>';
wp-includes/functions.php:          return date_i18n( $dateformatstring, $i );
wp-includes/general-template.php:                                               $arc_week_start = date_i18n($archive_week_start_date_format, $arc_week['start']);
wp-includes/general-template.php:                                               $arc_week_end = date_i18n($archive_week_end_date_format, $arc_week['end']);
wp-includes/post-template.php:  $date = date_i18n( $datef, strtotime( $revision->post_modified_gmt . ' +0000' ) );

#8 @Denis-de-Bernardy
6 years ago

There are quite a few more, actually, that come from the use of $wp_locale->get_month() and the like.

#9 @nbachiyski
6 years ago

  • Milestone changed from 3.0 to Future Release

#10 @waclawjacek
4 years ago

In case this is of any importance: I have solved this problem in the Polish translation by applying a regexp hack to pl_PL.php - http://i18n.svn.wordpress.org/pl_PL/tags/3.3.1/dist/wp-content/languages/pl_PL.php. This obviously isn't something that is guaranteed to work in all situations, but so far it's been enough. :) Something more reliable would be nicer, but at the moment this patch isn't required.

#11 @SergeyBiryukov
4 years ago

  • Keywords early removed
  • Milestone changed from Future Release to 3.4

Something similar is needed for ru_RU. Let's find the best option to bring this into core before the freeze.

Related: #19603

#12 @AndyDeGroo
4 years ago

  • Cc AndyDeGroo added

I landed here because I'm also looking for a way to make this work. In my case it's for Latvian.
It would be neat if we had an optional parameter for date_i18n and it would not mess with existing code if the param was added after $gmt. That way we could use it in filter function and pass the param as gettext context to translate our month and weekday names in correct form.

Changes in other core files where date_i18n is used should also be made, but this one is easy to introduce in core functions.php without breaking other code.

Maybe someone closer to core devs should try to bring more attention to this ticket.

#13 @SergeyBiryukov
4 years ago

  • Milestone changed from 3.4 to Future Release

#15 @Daedalon
2 years ago

As Denis-de-Bernardy referred to 4 years ago, different languages have different declensions. In the original example where Polish uses locative, Finnish uses inessive, and where Polish uses genitive, Finnish uses nominative. In Russian it's the same except prepositional instead of inessive.

The solution to the issue should allow specifying "in January" or "on Monday" in a way that gets translated correctly regardless of what the declination is called in the current language.

The simplest way might be to have direct translations from English that date_i18n then retrieves upon request. As long as date_i18n understands when it should be looking for the equivalent of "in January" instead of "January", it can return the appropriate translated string.

#16 @Daedalon
2 years ago

  • Cc daedalon@… added

#17 @Daedalon
2 years ago

#9396 duplicate/related.

#18 @SergeyBiryukov
11 months ago

#30771 was marked as a duplicate.

#19 @SergeyBiryukov
11 months ago

#30953 was marked as a duplicate.

#20 @SergeyBiryukov
11 months ago

  • Milestone changed from Future Release to 4.2

#21 @DrewAPicture
9 months ago

  • Keywords has-patch needs-refresh added
  • Owner changed from nbachiyski to SergeyBiryukov
  • Status changed from new to reviewing

Patch needs a refresh. I'll leave this up to @SergeyBiryukov on whether this is viable for 4.2 inclusion.

This ticket was mentioned in Slack in #core by drew. View the logs.

9 months ago

#23 @SergeyBiryukov
9 months ago

  • Milestone changed from 4.2 to Future Release

#24 @wonderboymusic
2 months ago

  • Milestone changed from Future Release to 4.4

This ticket was mentioned in Slack in #core by sergey. View the logs.

7 weeks ago

#26 @SergeyBiryukov
7 weeks ago

  • Keywords needs-refresh removed
  • Priority changed from low to normal

Adding a context to date_i18n() doesn't really solve anything, because the correct case depends on date format being used, not on the string placement.

date_i18n( 'F Y' ) doesn't need declension for example, but date_i18n( 'j F Y' ) does.

Polish and Croatian packages currently use a regex filter as a workaround.

11226.3.diff brings that into core, so that other Slavic languages (where similar rules apply) could use it too.

It also has the Catalan filter, so these three locales can remove their $locale.php files once this is in core.

#27 @SergeyBiryukov
6 weeks ago

To clarify, we're not trying to solve the original example here, "View posts published in January 2009". Currently there are no strings like that in core or default themes.

What we're trying to solve here is the lack of genitive case required by Slavic languages in certain date formats, like date_i18n( 'j F Y' ). Per comment:10, this should be sufficient to resolve the ticket for now.

This ticket was mentioned in Slack in #core-i18n by sergey. View the logs.

6 weeks ago

#29 @waclawjacek
6 weeks ago

Looks cool!

#30 @wonderboymusic
5 weeks ago

  • Type changed from enhancement to task (blessed)

This ticket was mentioned in Slack in #core by wonderboymusic. View the logs.

3 weeks ago

#32 @SergeyBiryukov
3 weeks ago

  • Resolution set to fixed
  • Status changed from reviewing to closed

In 35517:

Introduce wp_maybe_decline_date() for languages where certain date formats need to be declined, and hook it to the date_i18n filter.

If the locale specifies that month names require a genitive case in certain formats like 'j F Y' or 'j. F', the month name will be replaced with a correct form.

Fixes #11226.

Note: See TracTickets for help on using tickets.