The wrong code is:
<?php if (!$block->isReadonly()): ?>
<div><input type="hidden" name="affect_product_custom_options" value="1"/></div>
<?php endif; ?>
<script>
require([
"jquery",
"Magento_Catalog/js/custom-options"
], function(jQuery){
jQuery(function ($) {
var fieldSet = $('#Custom_Options');
fieldSet.customOptions(<?php /* @escapeNotVerified */ echo $this->helper('Magento\Framework\Json\Helper\Data')->jsonEncode(
[
'fieldId' => $block->getFieldId(),
'productGridUrl' => $block->getProductGridUrl(),
'formKey' => $block->getFormKey(),
'customOptionsUrl' => $block->getCustomOptionsUrl(),
'isReadonly' => $block->isReadonly(),
'itemCount' => $block->getItemCount(),
]
)?>);
The bug is quite tricky, let’s explain it.
What is Custom_Options
html element id?
This is an id autogenerated by jQuery UI
library based on the element’s title
attribute value:
// panel ids (idPrefix option + title attribute)
$.widget( "ui.tabs", $.ui.tabs, {
options: {
idPrefix: "ui-tabs-"
},
_tabId: function( tab ) {
var a = tab.is( "li" ) ? tab.find( "a[href]" ) : tab;
a = a[0];
return $( a ).closest( "li" ).attr( "aria-controls" ) ||
a.title && a.title.replace( /\s/g, "_" ).replace( /[^\w\u00c0-\uFFFF\-]/g, "" ) ||
this.options.idPrefix + getNextTabId();
}
});
// _createPanel method
$.widget( "ui.tabs", $.ui.tabs, {
options: {
panelTemplate: "<div></div>"
},
So the «Custom Options» tab functionality will not work with non-English locale because there will no an element with Custom_Options
html id.
There are multiple ways to fix the issue. I propose 2 of them: the first is simple and the second is more resistant to the future code changes.
Fix #1 (simple)
Replace the wrong line
<?php if (!$block->isReadonly()): ?>
<div><input type="hidden" name="affect_product_custom_options" value="1"/></div>
<?php endif; ?>
<script>
require([
"jquery",
"Magento_Catalog/js/custom-options"
], function(jQuery){
jQuery(function ($) {
var fieldSet = $('#Custom_Options');
fieldSet.customOptions(<?php /* @escapeNotVerified */ echo $this->helper('Magento\Framework\Json\Helper\Data')->jsonEncode(
[
'fieldId' => $block->getFieldId(),
'productGridUrl' => $block->getProductGridUrl(),
'formKey' => $block->getFormKey(),
'customOptionsUrl' => $block->getCustomOptionsUrl(),
'isReadonly' => $block->isReadonly(),
'itemCount' => $block->getItemCount(),
]
)?>);
with the new one:
var fieldSet = $("[aria-labelledby='product_info_tabs_customer_options']");
or
var fieldSet = $('#product-custom-options-wrapper').parent();
Fix #2 (more resistant to the future changes)
Leys’s look closely at the jQuery UI _tabId
method implementation:
// panel ids (idPrefix option + title attribute)
$.widget( "ui.tabs", $.ui.tabs, {
options: {
idPrefix: "ui-tabs-"
},
_tabId: function( tab ) {
var a = tab.is( "li" ) ? tab.find( "a[href]" ) : tab;
a = a[0];
return $( a ).closest( "li" ).attr( "aria-controls" ) ||
a.title && a.title.replace( /\s/g, "_" ).replace( /[^\w\u00c0-\uFFFF\-]/g, "" ) ||
this.options.idPrefix + getNextTabId();
}
});
// _createPanel method
$.widget( "ui.tabs", $.ui.tabs, {
options: {
panelTemplate: "<div></div>"
},
As you can see, we can set up aria-controls
attribute for the contailer’s LI element and it will be used as the id for the tabs widget.
In can be done here:
</div>
<?php endif ?>
<ul <?php /* @escapeNotVerified */ echo $block->getUiId('tab', $block->getId()) ?> class="<?php /* @escapeNotVerified */ echo $block->getIsHoriz() ? 'tabs-horiz' : 'tabs admin__page-nav-items' ?>">
<?php foreach ($tabs as $_tab): ?>
<?php if (!$block->canShowTab($_tab)): continue; endif; ?>
<?php $_tabClass = 'tab-item-link ' . $block->getTabClass($_tab) . ' ' . (preg_match('/\s?ajax\s?/', $_tab->getClass()) ? 'notloaded' : '') ?>
<?php $_tabType = (!preg_match('/\s?ajax\s?/', $_tabClass) && $block->getTabUrl($_tab) != '#') ? 'link' : '' ?>
<?php $_tabHref = $block->getTabUrl($_tab) == '#' ? '#' . $block->getTabId($_tab) . '_content' : $block->getTabUrl($_tab) ?>
<li class="admin__page-nav-item" <?php if ($block->getTabIsHidden($_tab)): ?> style="display:none"<?php endif; ?><?php /* @escapeNotVerified */ echo $block->getUiId('tab', 'item', $_tab->getId()) ?>>
<a href="<?php /* @escapeNotVerified */ echo $_tabHref ?>" id="<?php /* @escapeNotVerified */ echo $block->getTabId($_tab) ?>" name="<?php /* @escapeNotVerified */ echo $block->getTabId($_tab, false) ?>" title="<?php /* @escapeNotVerified */ echo $block->getTabTitle($_tab) ?>"
class="admin__page-nav-link <?php /* @escapeNotVerified */ echo $_tabClass;?>"
data-tab-type="<?php /* @escapeNotVerified */ echo $_tabType;?>"
<?php /* @escapeNotVerified */ echo $block->getUiId('tab', 'link', $_tab->getId()) ?>>
<span><?php /* @escapeNotVerified */ echo $block->getTabLabel($_tab); ?></span>
<span class="admin__page-nav-item-messages" data-role="item-messages">
<span class="admin__page-nav-item-message _changed">
<span class="admin__page-nav-item-message-icon"></span>