| 1091 | * in the object at the requested location. |
| 1092 | */ |
| 1093 | const localeAccessor = (locale, singular, allowDelayedTraversal) => { |
| 1094 | // Bail out on non-existent locales to defend against internal errors. |
| 1095 | if (!locales[locale]) return Function.prototype |
| 1096 | |
| 1097 | // Handle object lookup notation |
| 1098 | const indexOfDot = objectNotation && singular.lastIndexOf(objectNotation) |
| 1099 | if (objectNotation && indexOfDot > 0 && indexOfDot < singular.length - 1) { |
| 1100 | // If delayed traversal wasn't specifically forbidden, it is allowed. |
| 1101 | if (typeof allowDelayedTraversal === 'undefined') |
| 1102 | allowDelayedTraversal = true |
| 1103 | // The accessor we're trying to find and which we want to return. |
| 1104 | let accessor = null |
| 1105 | // An accessor that returns null. |
| 1106 | const nullAccessor = () => null |
| 1107 | // Do we need to re-traverse the tree upon invocation of the accessor? |
| 1108 | let reTraverse = false |
| 1109 | // Split the provided term and run the callback for each subterm. |
| 1110 | singular.split(objectNotation).reduce((object, index) => { |
| 1111 | // Make the accessor return null. |
| 1112 | accessor = nullAccessor |
| 1113 | // If our current target object (in the locale tree) doesn't exist or |
| 1114 | // it doesn't have the next subterm as a member... |
| 1115 | if ( |
| 1116 | object === null || |
| 1117 | !Object.prototype.hasOwnProperty.call(object, index) |
| 1118 | ) { |
| 1119 | // ...remember that we need retraversal (because we didn't find our target). |
| 1120 | reTraverse = allowDelayedTraversal |
| 1121 | // Return null to avoid deeper iterations. |
| 1122 | return null |
| 1123 | } |
| 1124 | // We can traverse deeper, so we generate an accessor for this current level. |
| 1125 | accessor = () => object[index] |
| 1126 | // Return a reference to the next deeper level in the locale tree. |
| 1127 | return object[index] |
| 1128 | }, locales[locale]) |
| 1129 | // Return the requested accessor. |
| 1130 | return () => |
| 1131 | // If we need to re-traverse (because we didn't find our target term) |
| 1132 | // traverse again and return the new result (but don't allow further iterations) |
| 1133 | // or return the previously found accessor if it was already valid. |
| 1134 | reTraverse ? localeAccessor(locale, singular, false)() : accessor() |
| 1135 | } else { |
| 1136 | // No object notation, just return an accessor that performs array lookup. |
| 1137 | return () => locales[locale][singular] |
| 1138 | } |
| 1139 | } |
| 1140 | |
| 1141 | /** |
| 1142 | * Allows delayed mutation of a translation nested inside objects. |