HackerOne users: Testing against this community violates our program's Terms of Service and will result in your bounty being denied.

English grammar errors when %n$s refers to the user.

edited July 2011 in Localization
I was correcting an error with $Definition['Activity.JoinCreated.FullHeadline'] and I noticed that that when referring to the user...
%1$s = "You"
%2$s = "You"
%3$s = "you"
%4$s = "your"

%2$s should be "Your" and ideally all of them should only be capitalized at the start of a sentence. I understand conditionally capitalization could be a huge pain, but if I could figure out where the default English text is, I could at least change %2$s.

I'm not a grammar-nut, but the person commissioning the site is an editor, and will definitely be irritated by this.
Tagged:

Best Answer

  • edited August 2011 Answer ✓
    I created the following sproc to run on databases which have already been affected by this bug.

    ------------------------------------------------------------------------
    -- Author: GeeksRock
    -- Note: This script can be used to reverse ActivityUserIDs and RegardingUserIDs.
    ------------------------------------------------------------------------

    DELIMITER $$

    CREATE PROCEDURE JoinCreatedIdReversal()
    BEGIN

    DECLARE maxActivityID INT(11) DEFAULT 1;
    DROP TABLE IF EXISTS ReverseUserEntries;

    CREATE TEMPORARY TABLE ReverseUserEntries
    SELECT
    gdn.ActivityID,
    gdn.CommentActivityID,
    gdn.ActivityTypeID,
    gdn.RegardingUserID AS 'ActivityUserIDReversal',
    gdn.ActivityUserID AS 'RegardingUserIDReversal',
    gdn.Story,
    gdn.Route,
    gdn.CountComments,
    gdn.InsertUserID,
    gdn.DateInserted
    FROM gdn_activity gdn;

    SELECT MAX(ActivityID) INTO maxActivityID FROM gdn_activity;
    SET maxActivityID = maxActivityID + 1;

    DELETE FROM gdn_activity WHERE ActivityID < maxActivityID;

    INSERT INTO gdn_activity
    (ActivityID,
    CommentActivityID,
    ActivityTypeID,
    ActivityUserID,
    RegardingUserID,
    Story,
    Route,
    CountComments,
    InsertUserID,
    DateInserted)
    SELECT * FROM ReverseUserEntries;

    END $$
    DELIMITER ;

Answers

  • (More information)

    Prior to editing, the text of $Definition['Activity.JoinCreated.FullHeadline'] was backwards and incorrectly possessive. For example, after I created an account for Bob, my activity page said "Bob created an account for your." (ungrammatical and inaccurate) and Bob's said "You created an account for JTadmin's." (grammatical, but still inaccurate).

    My three attempts to correct this have been:
    $Definition['Activity.JoinCreated.FullHeadline'] = '%3$s created an account for %1$s.';
    $Definition['Activity.JoinCreated.FullHeadline'] = 'An account for %1$s was created by %3$s.';
    $Definition['Activity.JoinCreated.FullHeadline'] = '%2$s account was created by %3$s.';

    The first gives an "you created an account for Bob." on my page. The second gives "An account for You was created by JTadmin." on Bob's page. The third gives "You account was created by JTadmin." on Bob's page.

    I'm going with the first option, because only a few moderators need to see the error. I can't think of anything that will be grammatically correct for both the user and the account creator.
  • Seems related to the issue #1010.
  • edited August 2011
    The issue is with the database insertion. I haven't had enough time to look around to find the correct file to modify, but I have been able to determine that the ActivityUserID is being inserted into the RegardingUserID field and likewise, the RegardingUserID is being inserted into the ActivityUserID field.

    Also, creating new users is the only time the Add User screen hangs (upon clicking Save, the data is written, but the screen doesn't close). When editing an existing user, clicking Save, saves changes and closes the screen.
  • edited August 2011
    Even after reversing the entries in the database, there's still an issue. Now, as the ActivityUser, I see: You created an account for newusername's.

    == In structure.php, this entry... ==
    if ($SQL->GetWhere('ActivityType', array('Name' => 'JoinCreated'))->NumRows() == 0)
    $SQL->Insert('ActivityType', array('AllowComments' => '1', 'Name' => 'JoinCreated', 'FullHeadline' => '%1$s created an account for %4$s.', 'ProfileHeadline' => '%1$s created an account for %4$s.'));

    == should read... ==
    if ($SQL->GetWhere('ActivityType', array('Name' => 'JoinCreated'))->NumRows() == 0)
    $SQL->Insert('ActivityType', array('AllowComments' => '1', 'Name' => 'JoinCreated', 'FullHeadline' => '%1$s created an account for %3$s.', 'ProfileHeadline' => '%1$s created an account for %3$s.'));

    However, I suppose, for existing databases, you'd have to write a query to manually update the entries.
  • Modifying this file solves the problem:
    c:\wamo\www\vanilla\applications\dashboard\models\class.activitymodel.php

    ==This signature==
    Add($ActivityUserID, $ActivityType, $Story = ' ', $RegardingUserID = ' ', $CommentActivityID = ' ', $Route = ' ', $SendEmail = ' ')

    ==should read==
    public function Add($RegardingUserID = ' ', $ActivityType, $Story = ' ', $ActivityUserID, $CommentActivityID = ' ', $Route = ' ', $SendEmail = ' ')
  • edited August 2011 Answer ✓
    I created the following sproc to run on databases which have already been affected by this bug.

    ------------------------------------------------------------------------
    -- Author: GeeksRock
    -- Note: This script can be used to reverse ActivityUserIDs and RegardingUserIDs.
    ------------------------------------------------------------------------

    DELIMITER $$

    CREATE PROCEDURE JoinCreatedIdReversal()
    BEGIN

    DECLARE maxActivityID INT(11) DEFAULT 1;
    DROP TABLE IF EXISTS ReverseUserEntries;

    CREATE TEMPORARY TABLE ReverseUserEntries
    SELECT
    gdn.ActivityID,
    gdn.CommentActivityID,
    gdn.ActivityTypeID,
    gdn.RegardingUserID AS 'ActivityUserIDReversal',
    gdn.ActivityUserID AS 'RegardingUserIDReversal',
    gdn.Story,
    gdn.Route,
    gdn.CountComments,
    gdn.InsertUserID,
    gdn.DateInserted
    FROM gdn_activity gdn;

    SELECT MAX(ActivityID) INTO maxActivityID FROM gdn_activity;
    SET maxActivityID = maxActivityID + 1;

    DELETE FROM gdn_activity WHERE ActivityID < maxActivityID;

    INSERT INTO gdn_activity
    (ActivityID,
    CommentActivityID,
    ActivityTypeID,
    ActivityUserID,
    RegardingUserID,
    Story,
    Route,
    CountComments,
    InsertUserID,
    DateInserted)
    SELECT * FROM ReverseUserEntries;

    END $$
    DELIMITER ;
  • lucluc ✭✭
    @Todd, @Tim: maybe some input about all this?
  • This question is a particular case of a more general questions in some other languages than english (at least french). In some languages, the sentence structure and word order can be completely different depending on who is the subject (verbs, plural of singular, gender...).

    I came up with the following solution, which works for french and is completely transparent to existing locales.

    Here is the principle : for all activities translation, the standard 'Activity.XXX.FullHeadline' is used by default, but you can add specific versions by adding suffixes (.You, .He or .Somebody). The first suffix is for the viewing user, and the second suffix is for the targeted user.

    If for an activity, you can come up with a generic translation, it works as before.
    If you need a more precise translation, you just add new entries in the $Definition table.

    $Definition['Activity.RoleChange.FullHeadline'] = '%1$s a changé les autorisations %3$s.';    
    $Definition['Activity.RoleChange.FullHeadline.You'] = '%1$s avez changé les autorisations %3$s.';
    $Definition['Activity.RoleChange.FullHeadline.Somebody.You'] = '%1$s a changé vos autorisations.';
    

    Step 1 : Add a GetActivityHeadline method to class Gdn_Format

    In the file library/core/class.format.php

    Look for the end of the ActivityHeadline method :

      return sprintf($MessageFormat, $ActivityName, $ActivityNameP, $RegardingName, $RegardingNameP, $RegardingWall, $Gender, $Gender2, $Route, $GenderSuffix, $RegardingWallLink, $ActivityRouteLink);
    

    }

    Insert after :

    static function GetActivityHeadline($Activity, $ViewingUserID, $ProfileUserID, $Headline, $Default) 
    {     if ($ViewingUserID == $Activity->ActivityUserID)
      { // activity from current user
        $From = "You";
        $To = ($ViewingUserID == $Activity->RegardingUserID ? "You" : ($ProfileUserID == $Activity->RegardingUserID ? 'He' : 'Somebody'));
      } else if ($ProfileUserID == $Activity->ActivityUserID)
      { $From = "He";
        $To = ($ViewingUserID == $Activity->RegardingUserID ? "You" : "Somebody");
      } else
      { $From = "Somebody";
        $To = ($ViewingUserID == $Activity->RegardingUserID ? "You" : "Somebody");
      }
    
      return
          T("Activity.{$Activity->ActivityType}.$Headline.$From.$To",
            T("Activity.{$Activity->ActivityType}.$Headline.$From",
              T("Activity.{$Activity->ActivityType}.$Headline", $Default)));
    

    }

    Step 2 : Have the new method called

    In the same file, in the ActivityHeadline method

    Look for :

      $FullHeadline = T("Activity.{$Activity->ActivityType}.FullHeadline", T($Activity->FullHeadline));
      $ProfileHeadline = T("Activity.{$Activity->ActivityType}.ProfileHeadline", T($Activity->ProfileHeadline));
    

    and replace those lines by ;

      $FullHeadline = self::GetActivityHeadline($Activity, $ViewingUserID, $ProfileUserID, "FullHeadline", T($Activity->FullHeadline)); 
      $ProfileHeadline = self::GetActivityHeadline($Activity, $ViewingUserID, $ProfileUserID, "ProfileHeadline", T($Activity->ProfileHeadline)); 
    

    Step 3 : Add specific translations as needed

    I can send to anyone interested my french translations using this mechanism.

    For example :

    $Definition['Activity.NewDiscussion.FullHeadline.You'] = '%1$s avez commencé une %8$s.';

  • 422422 Developer MVP

    Your on fire dude good one thanks

    There was an error rendering this rich post.

  • ArachnosArachnos La Garenne Colombes

    @Olivier_Chevet J'ai envoyé une demande d'intégration de tes corrections : bien vu ;-)

Sign In or Register to comment.