Answers.Body: <blockquote>
    <p>The part that I'm not "getting" is I think there should be one Element in craft_elements and then for each localization, there should be one record in craft_elements_i18n yes? </p>
  </blockquote>
  
  <p>Yes.</p>
  
  <blockquote>
    <p>And then for each localization, there should be a separate record in my craft_seomatic_meta table for each localized version yes?</p>
  </blockquote>
  
  <p>Only if the values in that table need to be stored on a per-locale basis, which to my knowledge has never been the case until now with SEOmatic.</p>
  
  <blockquote>
    <p>When I call $result = craft()->elements->getElementById($metaId, 'Seomatic_Meta', $locale); how does it "know" which record to look up to load the returned Seomatic_MetaElementType with data?</p>
  </blockquote>
  
  <p>Any time you run an element query (which <code>getElementById()</code> does), the element type’s <a href="https://craftcms.com/classreference/elementtypes/IElementType#modifyElementsQuery-detail"><code>modifyElementsQuery()</code></a> method will be called, which gives the element type a chance to make changes to the query. In <a href="https://github.com/khalwat/seomatic/blob/master/elementtypes/Seomatic_MetaElementType.php#L156">yours</a>, you have the following code:</p>
  
  <pre><code>$query
      -&gt;addSelect('seomatic_meta.*')
      -&gt;join('seomatic_meta seomatic_meta', 'seomatic_meta.elementid = elements.id')
      -&gt;andWhere(DbHelper::parseParam('seomatic_meta.locale', $criteria-&gt;locale, $query-&gt;params));
  </code></pre>
  
  <p>That condition you’re adding to the query on the <code>seomatic_meta.locale</code> column is what is ensuring that the correct localized row in your <code>seomatic_meta</code> table will be included in the result.</p>
  
  <p>That’s just for <em>selecting</em> elements though. I might be missing something, but looking at your <a href="https://github.com/khalwat/seomatic/blob/master/services/SeomaticService.php#L683">SeomaticService::saveMeta()</a> method, it doesn’t look like you’re ever ensuring that all of the localized rows are actually getting saved. If you take a look through <a href="https://craftcms.com/classreference/services/ElementsService#saveElement-detail">ElementsService::saveElement()</a>, you will see that one of the things it does is loop through the locales returned by <code>$element-&gt;getLocales()</code> and make sure that there’s an ElementLocaleRecord (elements_i18n row) for the element in each of those locales. If you want to store rows for each locale in your own craft_seomatic_meta table, it’s the plugin’s responsibility to do that, not Craft’s.</p>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2016-09-01T23:41:59.627Z
Answers.Text: @BrandonKelly - Above you say that we can add support for grabbing a particular locale using the `modifyElementsQuery()` method.  You point to the example coding adding an `andWhere` clause to do so. In looking at the `EntryElementType` and `CategoryElementType`, neither of those Elements seems to be limiting the result by locale in the `modifyElementsQuery()` method.  Why are the above example and the Entry and Category Elements different? What am I missing?
Answers.UserDisplayName: Ben Parizek
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2016-09-02T12:29:03.887Z
Answers.Text: @BenParizek Because none of the built-in element types need to store data on a per-locale basis, besides whatever’s in `elements_i18n` and `content` (and those tables are already joined in before modifyElementsQuery() is even called).
Answers.UserDisplayName: Brandon Kelly
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2015-12-24T08:22:33.847Z
Answers.Text: I was planning to store different data on a per-locale basis, just as I do with my regular old records.  You saying that no one else has needed/wanted to do this makes me think that I'm doing something wrong?
  
  Should I not be storing this data in my own table?  The "normal" way to do this would be to make a FieldType, and just have Craft handle the gory details, storing it in `craft_content`?
  
  I feel like perhaps I'm doing something wrong, if it's something no one else is doing.
Answers.UserDisplayName: andrew.welch
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2015-12-24T15:46:55.510Z
Answers.Text: @khalwat No to be clear I think you’re going about it the right way. This is just the first plugin (that I can think of) that needs to provide fields that store _content_, but not via custom fields.
Answers.UserDisplayName: Brandon Kelly
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2015-12-26T05:32:48.387Z
Answers.Text: @khalwat: If it makes you feel better, I've recently gotten the feature request to make Smart Map's "Address" field translatable... But Brandon's right, AFAIK you're the first plugin dev to actually _try_ it. This is all great info, thanks to both of you guys!
Answers.UserDisplayName: Lindsey D
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2015-12-23T18:37:31.983Z
Answers.LastActivityDate: 2015-12-23T18:37:31.983Z
Answers.UserDisplayName: Brandon Kelly
Body: <p>My question is re: localization of ElementTypes in a plugin.  I have the records all working fine in multiple locales.</p>
  
  <p>The part that I'm not "getting" is I think there should be one Element in <code>craft_elements</code> and then for each localization, there should be one record in <code>craft_elements_i18n</code> yes?  And then for each localization, there should be a separate record in my <code>craft_seomatic_meta</code> table for each localized version yes?</p>
  
  <p>This is where in my controller it saves the ElementType: <a href="https://github.com/khalwat/seomatic/blob/master/controllers/SeomaticController.php#L173" rel="nofollow">https://github.com/khalwat/seomatic/blob/master/controllers/SeomaticController.php#L173</a></p>
  
  <p>And here is the function is calls in my service to save the element &amp; record: <a href="https://github.com/khalwat/seomatic/blob/master/services/SeomaticService.php#L683" rel="nofollow">https://github.com/khalwat/seomatic/blob/master/services/SeomaticService.php#L683</a></p>
  
  <p>When I call <code>$result = craft()-&gt;elements-&gt;getElementById($metaId, 'Seomatic_Meta', $locale);</code> how does it "know" which record to look up to load the returned <code>Seomatic_MetaElementType</code> with data?</p>
  
  <p>I'm clearly missing something basic regarding how this should all work</p>
  
Tags: <plugin-development><localization>
Title: Localized ElementTypes in a plugin
ThreadText: # Localized ElementTypes in a plugin
  
  (Asked by: username_0 on 2015-12-23)
  
  My question is re: localization of ElementTypes in a plugin. I have the records all working fine in multiple locales.
  
  The part that I'm not "getting" is I think there should be one Element in `craft_elements` and then for each localization, there should be one record in `craft_elements_i18n` yes? And then for each localization, there should be a separate record in my `craft_seomatic_meta` table for each localized version yes?
  
  This is where in my controller it saves the ElementType: <https://github.com/khalwat/seomatic/blob/master/controllers/SeomaticController.php#L173>
  
  And here is the function is calls in my service to save the element & record: <https://github.com/khalwat/seomatic/blob/master/services/SeomaticService.php#L683>
  
  When I call `$result = craft()->elements->getElementById($metaId, 'Seomatic_Meta', $locale);` how does it "know" which record to look up to load the returned `Seomatic_MetaElementType` with data?
  
  I'm clearly missing something basic regarding how this should all work
  
  **Tags:** plugin-development, localization
  
  
  ---
  
  ## 1 answers
  
  ### Answer by username_1 on 2015-12-23. Score: 5
  
  > The part that I'm not "getting" is I think there should be one Element in craft\_elements and then for each localization, there should be one record in craft\_elements\_i18n yes?
  
  Yes.
  
  > And then for each localization, there should be a separate record in my craft\_seomatic\_meta table for each localized version yes?
  
  Only if the values in that table need to be stored on a per-locale basis, which to my knowledge has never been the case until now with SEOmatic.
  
  > When I call $result = craft()->elements->getElementById($metaId, 'Seomatic\_Meta', $locale); how does it "know" which record to look up to load the returned Seomatic\_MetaElementType with data?
  
  Any time you run an element query (which `getElementById()` does), the element type’s [`modifyElementsQuery()`](https://craftcms.com/classreference/elementtypes/IElementType#modifyElementsQuery-detail) method will be called, which gives the element type a chance to make changes to the query. In [yours](https://github.com/khalwat/seomatic/blob/master/elementtypes/Seomatic_MetaElementType.php#L156), you have the following code:
  
  ```
  $query
      ->addSelect('seomatic_meta.*')
      ->join('seomatic_meta seomatic_meta', 'seomatic_meta.elementid = elements.id')
      ->andWhere(DbHelper::parseParam('seomatic_meta.locale', $criteria->locale, $query->params));
  
  ```
  
  That condition you’re adding to the query on the `seomatic_meta.locale` column is what is ensuring that the correct localized row in your `seomatic_meta` table will be included in the result.
  
  That’s just for *selecting* elements though. I might be missing something, but looking at your [SeomaticService::saveMeta()](https://github.com/khalwat/seomatic/blob/master/services/SeomaticService.php#L683) method, it doesn’t look like you’re ever ensuring that all of the localized rows are actually getting saved. If you take a look through [ElementsService::saveElement()](https://craftcms.com/classreference/services/ElementsService#saveElement-detail), you will see that one of the things it does is loop through the locales returned by `$element->getLocales()` and make sure that there’s an ElementLocaleRecord (elements\_i18n row) for the element in each of those locales. If you want to store rows for each locale in your own craft\_seomatic\_meta table, it’s the plugin’s responsibility to do that, not Craft’s.
  
  > **Comments:**
  > **username_0**: I was planning to store different data on a per-locale basis, just as I do with my regular old records.  You saying that no one else has needed/wanted to do this makes me think that I'm doing something wrong?  Should I not be storing this data in my own table?  The "normal" way to do this would be to make a FieldType, and just have Craft handle the gory details, storing it in `craft_content`?  I feel like perhaps I'm doing something wrong, if it's something no one else is doing.  
  > **username_1**: @khalwat No to be clear I think you’re going about it the right way. This is just the first plugin (that I can think of) that needs to provide fields that store _content_, but not via custom fields.  
  > **username_3**: @khalwat: If it makes you feel better, I've recently gotten the feature request to make Smart Map's "Address" field translatable... But username_1's right, AFAIK you're the first plugin dev to actually _try_ it. This is all great info, thanks to both of you guys!  
  > **username_2**: @username_1 - Above you say that we can add support for grabbing a particular locale using the `modifyElementsQuery()` method.  You point to the example coding adding an `andWhere` clause to do so. In looking at the `EntryElementType` and `CategoryElementType`, neither of those Elements seems to be limiting the result by locale in the `modifyElementsQuery()` method.  Why are the above example and the Entry and Category Elements different? What am I missing?  
  > **username_1**: @username_2 Because none of the built-in element types need to store data on a per-locale basis, besides whatever’s in `elements_i18n` and `content` (and those tables are already joined in before modifyElementsQuery() is even called).  
  
  ---
  
  